简体   繁体   中英

Strange NullPointerException error in android when using custom suggestions provider

I am trying to make custom search suggestions in my app. I've started from documentation and Searchable dictionary example. However, this example isn't so good for me so I've started with some tests to find out exactly how to make it, because there is not much tutorials in the Internet also.

Generally my app has right now 2 databases – one normal and second with less number of columns – FTS3. What I would like to achieve is to connect suggestions provider to this FTS3 table.

What I was trying to do was to now was, using simple function, return in suggestions whole DB (around 200 records) after typing any letter in search box. I know about limit 50 records, but I don't think it is the problem. This are fragments from Provider's code. What I found out, that when you type in text, provider goes to option SEARCH_SUGGEST :

// UriMatcher stuff
    private static final int SEARCH_WORDS = 0;
    private static final int GET_WORD = 1;
    private static final int SEARCH_SUGGEST = 2;
    private static final int REFRESH_SHORTCUT = 3;
    private static final UriMatcher mUriMatcher = buildUriMatcher();

    /**
     * Builds up a UriMatcher for search suggestion and shortcut refresh queries.
     */
    private static UriMatcher buildUriMatcher() {
        Log.d(TAG,"urimatcher");
        UriMatcher matcher =  new UriMatcher(UriMatcher.NO_MATCH);
        // to get definitions...
        matcher.addURI(AUTHORITY, "mydb", SEARCH_WORDS);
        matcher.addURI(AUTHORITY, "mydb/#", GET_WORD);
        // to get suggestions...
        matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
        matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);

        return matcher;
    }

@Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

switch (mUriMatcher.match(uri)) {
            case SEARCH_SUGGEST:
                Log.d(TAG,"SEARCH_SUGGEST");
                if (selectionArgs == null) {
                  throw new IllegalArgumentException(
                      "selectionArgs must be provided for the Uri: " + uri);
                }
                return getSuggestions(selectionArgs[0]);
            case SEARCH_WORDS:
                Log.d(TAG,"SEARCH_WORDS");
                if (selectionArgs == null) {
                  throw new IllegalArgumentException(
                      "selectionArgs must be provided for the Uri: " + uri);
                }
                return search(selectionArgs[0]);
            case GET_WORD:
                Log.d(TAG,"GET_WORD");
                return null;
            default:
                Log.d(TAG,"default");
                throw new IllegalArgumentException("Unknown Uri: " + uri);
        }
    }

private Cursor getSuggestions(String query) {
        String[] columns = { MyDBAdapter.KEY_TITLE,MyDBAdapter.KEY_ID};
              Log.d(TAG,"query1: " + query);

              try{
                  Cursor tmp = MyDB.getAllEntriesFTS(false, columns,
                        null, null, null, null, MyDBAdapter.KEY_TITLE, null, query);
              Log.d(TAG,"cursor: " + Integer.toString(tmp.getCount()));
              }
              catch(Exception e)
              {
                  Log.d(TAG,e.toString());
              }
              return tmp;
    }

In getSuggestions I put code that should generally work, but it doesn't. Doesn't work only when used here. When I used it in other activity to get cursor for listview everything was fine. Here it returns my NullPointerException.

So getting deeper I put also some Log tags in getAllEntriesFTS method and this method looks like this:

public Cursor getAllEntriesFTS(boolean distinct, String[] result_columns,
            String selection, String[] selectionArgs, String groupBy,
            String having, String orderBy, String limit, String query) {

        Log.d(TAG,"query db: " + query);

        String[] columns = { MyDBAdapter.KEY_TITLE, MyDBAdapter.KEY_ID};

        Log.d(TAG,"columns: " + Integer.toString(result_columns.length));

        Cursor allRows = null;
        try{
allRows = db.query(distinct, DATABASE_TABLE_FTS, columns,
                    null, null, null, null, MyDBAdapter.KEY_TITLE, null);
            Log.d(TAG,"OK");
        }
        catch(Exception e)
        {
            Log.d(TAG, e.toString());//it always goes there with NullPointerExceptionwhen used in provider
        }
        Log.d(TAG,Integer.toString(allRows.getCount()));
        return allRows;
    }

So, generalny speaking it should return cursor to whole DB, but instead it throws In place where it shouldn't NullPointerException.

Can someone please tell me what am I doing wrong and how it should be done?

Thank's to JB Nizet I was able to find my mistake. I was thinking I've studied Google's example good, but I was wrong.

The problem was lack of database open before cursor call. It should look like this:

private Cursor getSuggestions(String query) {
        String[] columns = { MyDBAdapter.KEY_TITLE,MyDBAdapter.KEY_ID};
              Log.d(TAG,"query1: " + query);

              try{
                  MyDB.open();
                  Cursor tmp = MyDB.getAllEntriesFTS(false, columns,
                        null, null, null, null, MyDBAdapter.KEY_TITLE, null, query);
                  MyDB.close();
              Log.d(TAG,"cursor: " + Integer.toString(tmp.getCount()));
              }
              catch(Exception e)
              {
                  Log.d(TAG,e.toString());
              }
              return tmp;
    }

Thank you all for showing me it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM