我在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" />
答案 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";
请检查。