getContentResolver()中光标的空对象

时间:2019-04-29 14:29:28

标签: android android-contentresolver

我在Android应用中使用SQLite。使用光标显示信息时遇到了问题。光标使用getContentResolver

我遇到了错误 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.memo/com.example.android.memo.Activity.MainActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'void android.database.Cursor.close()' on a null object reference

我查看了我的Provider类,首先是因为查询方法返回了null。但是,我将其更改为返回光标,但仍然无法正常工作。

这是我的片段中使用游标的代码: InboxFragment.java

public class InboxFragment extends Fragment {

    TextView displayView;
    TodoDBHelper mDBHelper;


    public InboxFragment() {
        // Required empty public constructor
    }


    @Override
    @TargetApi(23)
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View root = inflater.inflate(R.layout.fragment_inbox, container, false);
        displayView = (TextView) root.findViewById(R.id.displayNumViews);
        mDBHelper = new TodoDBHelper(getContext());
        displayDatabaseInfo(displayView);
        return root;


    }


    @Override
    public void onStart() {
        displayDatabaseInfo(displayView);
        super.onStart();
    }

    public void displayDatabaseInfo(TextView displayView) {
        // Define a projection that specifies which columns from the database
        // you will actually use after this query.
        String[] projection = {
                TodoEntry._ID,
                TodoEntry.COLUMN_TODO_NAME};

        Cursor cursor = getContext().getContentResolver().query(TodoEntry.CONTENT_URI,
                projection, null, null, null);

        try {

            displayView.setText("There are " + cursor.getCount() + " tasks.\n\n");
            int idColumnIndex = cursor.getColumnIndex(TodoEntry._ID);
            int nameColumnIndex = cursor.getColumnIndex(TodoEntry.COLUMN_TODO_NAME);

            while (cursor.moveToNext()) {

                int currentID = cursor.getInt(idColumnIndex);
                String currentName = cursor.getString(nameColumnIndex);

                // Display the values from each column of the current row in the cursor in the TextView
                displayView.append(("\n" + currentID + " - " +
                        currentName));
            }
        } finally {
            cursor.close();
        }
    }
}

以下是Contract类TodoContract.java

中的代码
public class TodoContract {

    private TodoContract(){}

    public static final String CONTENT_AUTHORITY = "com.example.android.todos";
    public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
    public static final String PATH_PETS = "todos";

    public static final class TodoEntry implements BaseColumns{
        public final static String TABLE_NAME = "Todos";

        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, PATH_PETS);

        public static final String CONTENT_LIST_TYPE =
                ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_PETS;

        public static final String CONTENT_ITEM_TYPE =
                ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_PETS;

        public final static String _ID = BaseColumns._ID;
        public final static String COLUMN_TODO_NAME = "name";
        public final static String COLUMN_TODO_TIME = "time";
        public final static String COLUMN_TODO_DATE = "date";
        public final static String COLUMN_TODO_CATEGORY = "category";
        public final static String COLUMN_TODO_PRIORITY = "priority";

    }
}

提供程序类TodoProvider的代码(仅相关部分)

package com.example.android.memo.database;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.example.android.memo.database.TodoContract.TodoEntry;

/**
 * Created by 21poonkw1 on 29/4/2019.
 */

public class TodoProvider extends ContentProvider {

    private TodoDBHelper mDBHelper;
    public static final String LOG_TAG = TodoProvider.class.getSimpleName();

    private static final int TODOS = 100;
    private static final int TODOS_ID = 101;
    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {

        sUriMatcher.addURI(TodoContract.CONTENT_AUTHORITY, TodoContract.PATH_PETS, TODOS);
        sUriMatcher.addURI(TodoContract.CONTENT_AUTHORITY, TodoContract.PATH_PETS + "/#", TODOS_ID);


    }

    @Override
    public boolean onCreate() {
        mDBHelper = new TodoDBHelper(getContext());
        return true;
    }

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

        SQLiteDatabase database = mDBHelper.getReadableDatabase();
        Cursor cursor;

        int match = sUriMatcher.match(uri);
        switch(match){

            case TODOS:
                cursor = database.query(TodoContract.TodoEntry.TABLE_NAME, projection,
                        selection, selectionArgs, null, null, sortOrder);
                break;
            case TODOS_ID:
                selection = TodoContract.TodoEntry._ID + "=?";
                selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
                cursor = database.query(TodoContract.TodoEntry.TABLE_NAME, projection,
                        selection, selectionArgs, null, null, sortOrder);
                break;
            default:
                throw new IllegalArgumentException("Cannot query unknown URI " + uri);


        }
        return cursor;
    }

... 
}

清单:

        <provider
            android:name=".database.TodoProvider"
            android:authorities="com.example.android.memo"
            android:exported="false" />

1 个答案:

答案 0 :(得分:0)

要解决该错误,请在光标上添加一个空检查。我怀疑查询方法是否仍返回null。

if(cursor!=null){
cursor.close();
}

我可以看到权限不匹配,

    android:authorities="com.example.android.memo"

以及您的代码TodoContract.java。

public static final String CONTENT_AUTHORITY = "com.example.android.todos";

请检查。