onLoadFinished()接收一个空游标

时间:2013-06-12 19:16:23

标签: android android-contentprovider android-sqlite

我正在尝试使用我创建的ContentProvider在我的活动中填充ListView,但是当调用onLoadFinished()方法时,它会收到一个null Cursor。 (尽管CursorLoader不为null) 我正在尝试调试ContentProvider,但调试器不会停止在query()方法上(它在URI不匹配时停止,当我修复它时,它不会停止!!!)。因此,如果没有调试,我很难找到为什么我的光标在onLoadFinished()方法上返回为null。
以下是活动的代码:

    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.app.LoaderManager;
    import android.support.v4.content.CursorLoader;
    import android.support.v4.content.Loader;
    import android.support.v4.widget.SimpleCursorAdapter;
    import android.view.Menu;
    import android.widget.ListView;

    public class PicturesListActivity extends FragmentActivity  
            implements LoaderManager.LoaderCallbacks<Cursor> {


        SimpleCursorAdapter myAdapter;

        String[] projection = {"_id", "name"};
        String[] from = {"name"};
        String orderBy = "year DESC";

        @Override
        protected void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_pictures_list);
            final ListView listview = (ListView) findViewById(R.id.lv_pictures_list);
            // The TextView in simple_list_item_1
            int[] toViews = {android.R.id.text1};
            // Prepare the loader.  Either re-connect with an existing one, or         start a new one.
            getSupportLoaderManager().initLoader(0, null, this);
            myAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, from, toViews, 0);
            listview.setAdapter(myAdapter);
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is         present.
            getMenuInflater().inflate(R.menu.pictures_list, menu);
            return true;
        }

        @Override
        // Called when a new Loader needs to be created (initLoader)
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            Uri uri = Uri.parse(DatabaseContentProvider.AUTHORITY + DatabaseContentProvider.TABLE_PATH_PICTURE);
            CursorLoader cl = new CursorLoader(this, uri, projection, null, null, orderBy);
            return cl;
        }

        @Override
        // Called automatically when a previously created loader has finished loading
        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
             myAdapter.swapCursor(data);
                                }

        @Override
        // Called when a previously created loader is reset, making the data unavailable
        public void onLoaderReset(Loader<Cursor> loader) {
            myAdapter.swapCursor(null);
                }

    }  

这是我创建的ContentProvider:

    import android.content.ContentProvider;
    import android.content.ContentValues;
    import android.content.UriMatcher;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteQueryBuilder;
    import android.net.Uri;
    import android.text.TextUtils;

    public class DatabaseContentProvider extends ContentProvider {

        //database
        private DatabaseAssetHelper dbhelper;
        //stuff
        public static final String AUTHORITY = "com.frlnrl.myapp.DatabaseContentProvider";
        public static final String TABLE_PATH_PICTURE = DatabaseContract.Pictures.TABLE_PICTURE;

        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);

        //UriMatcher
        private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        static {
            sURIMatcher.addURI(AUTHORITY, TABLE_PATH_PICTURE , 37);
        }   

        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            // TODO Auto-generated method stub
            int numberOfLinesDeleted = 0;
            return numberOfLinesDeleted;
        }

        @Override
        public String getType(Uri uri) {
            return null;
        }

        @Override
        public Uri insert(Uri uri, ContentValues values) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public boolean onCreate() {
            dbhelper = new DatabaseAssetHelper(getContext());
            return true;
        }

        @Override
        public Cursor query(Uri uri, String[] projection, String selection,
                String[] selectionArgs, String sortOrder) {
            SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
            SQLiteDatabase db = dbhelper.getReadableDatabase();
            int uriReceived = sURIMatcher.match(uri);
            switch (uriReceived) {
                case 37:
                    if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC";
                    queryBuilder.setTables(DatabaseContract.Pictures.TABLE_PICTURE);
                    break;  
                        default:
                            throw new IllegalArgumentException("Unknown oh eu aqui URI");
            }
            Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
            cursor.setNotificationUri(getContext().getContentResolver(), uri);
            return cursor;
        }

        @Override
        public int update(Uri uri, ContentValues values, String selection,
                String[] selectionArgs) {
            // TODO Auto-generated method stub
            int numberOfLineUpdated = 0;
            return numberOfLineUpdated;
        }

    }  

有没有人知道为什么返回一个空光标?

1 个答案:

答案 0 :(得分:2)

首先,您应该为您的路径修复CONTENT_URI。 变化

public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);

public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + TABLE_PATH_PICTURE);

您未在Uri上添加路径。

然后在创建游标加载器时,你可以使用CONTENT_URI,而不是每次尝试解析Uri(你做错了导致你的游标加载器试图查询不存在的Uri并返回一个空游标)

@Override
// Called when a new Loader needs to be created (initLoader)
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    Uri uri = DatabaseContentProvider.CONTENT_URI;
    CursorLoader cl = new CursorLoader(this, uri, projection, null, null, orderBy);
    return cl;
}