在android开发中,我们经常用SimpleCursorAdapter来绑定数据库里面的数据,很多人在使用这个类的时候并不知道具体怎么样来用,或者说还有很多疑问,比如最后一个参数该怎么写,这个cursor什么时候关闭,是怎么管理cursor的等等。
在android的不同的版本中,对SimpleCursorAdapter的使用方法是不同的,我们先来看下SimpleCursorAdapter构造方法,SimpleCursorAdapter有两个构造方法,其实可以归并为一个构造方法,我们看下构造方法的说明:
我们看最后一个参数flags,它有两个值可以选择分别为:CursorAdapter.FLAG_AUTO_REQUERYCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER,另外一个构造方法就是少了最后一个参数,默认被设置为CursorAdapter.FLAG_AUTO_REQUERY
首先我们来看没有flag参数或者参数为CursorAdapter.FLAG_AUTO_REQUERY 的情况,这种是在android3.0以下版本中才使用的,在分为android3.0及以上的版本中,已经被废弃了,是不建议使用的,我们还是来说明下使用方法

        final Cursor c = managedQuery(Persons.CONTENT_URI, null, null, null, null);        SimpleCursorAdapter simpleCursorAdapter = new SimpleCursorAdapter(                this,                R.layout.list_item,                c,                new String[] {Persons.NAME, Persons.AGE},                new int[] {R.id.textViewName, R.id.textViewAge}        );        ListView listView = (ListView)findViewById(R.id.listView);        listView.setAdapter(simpleCursorAdapter);

正如字面意思,FLAG_AUTO_REQUERY会自动查询如果数据库中的数据发生了变化以实时反映到界面上来,这样使用有一个问题,查询数据是发生在UI线程中,会造成卡顿的现象,甚至出现ANR异常,取决于手机的配置及数据的大小,这也是android3.0及以上放弃的原因,尽管如此,我们还是有些问题需要来理解。
一般来说我们使用Cursor需要close,但是在这里我们并没close,那么是怎么处理的呢,原理是Activity自己帮我处理的,大家看我是使用managedQuery来获取Cursor对象的,在这个方法中

@Deprecatedpublic final Cursor managedQuery(Uri uri, String[] projection, String selection,        String[] selectionArgs, String sortOrder) {    Cursor c = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);    if (c != null) {        startManagingCursor(c);    }    return c;}

用getContentResolver().query()获取到Cursor对象以后,使用startManagingCursor()把Cursor对象加入到Activity中管理。我们看下startManagingCursor方法

    @Deprecated    public void startManagingCursor(Cursor c) {        synchronized (mManagedCursors) {            mManagedCursors.add(new ManagedCursor(c));        }    }

以Cursor构建了一个ManagedCursor对象,并加入到一个类型为ArrayList的mManagedCursors容器里面去了,在Activity中的onDestroy()方法中,我们看到下面的代码

        // close any cursors we are managing.        synchronized (mManagedCursors) {            int numCursors = mManagedCursors.size();            for (int i = 0; i < numCursors; i++) {                ManagedCursor c = mManagedCursors.get(i);                if (c != null) {                    c.mCursor.close();                }            }            mManagedCursors.clear();        }

没错,从mManagedCursors循环取出所有的ManagedCursor对象,并关闭里面的Cursor,在Activity中的performRestart()方法,我们看到如下代码

            synchronized (mManagedCursors) {                final int N = mManagedCursors.size();                for (int i=0; i                    ManagedCursor mc = mManagedCursors.get(i);                    if (mc.mReleased || mc.mUpdated) {                        if (!mc.mCursor.requery()) {                            if (getApplicationInfo().targetSdkVersion                                    >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {                                throw new IllegalStateException(                                        "trying to requery an already closed cursor  "                                        + mc.mCursor);                            }                        }                        mc.mReleased = false;                        mc.mUpdated = false;                    }                }            }

我们看到了mCursor.requery()方法,这个方法是用来重新查询数据,在Activity重新开始的时候,performRestart()方法是Activity重新开始过程会被调用的方法。这下大家明白Activity是怎么管理Cursor的吧!注意如果大家在使用这个的时候一定要managedQuery()方法来获取Cursor,不然Cursor没被Activity管理,会游离在外,有可能会出现游标未关闭异常,大家最好不用这种方法了,android已经废弃!!!
然后我们看使用第二个参数来构建SimpleCursorAdapter对象即Flag为CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER,这是android3.0及以上的做法,我们需要使用到CursorLoader来加载数据了

        simpleCursorAdapter =  new SimpleCursorAdapter(                this,                R.layout.list_item,                null,                 new String[] {Persons.NAME, Persons.AGE},                new int[] {R.id.textViewName, R.id.textViewAge},                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER        );        ListView listView = (ListView)findViewById(R.id.listView);        listView.setAdapter(simpleCursorAdapter);        LoaderManager loaderManager = getLoaderManager();        loaderManager.initLoader(0, null, this);

在回调方法中写上对应的代码

    @Override    public Loader onCreateLoader(int id, Bundle args) {        return new CursorLoader(this, Persons.CONTENT_URI, null, null, null, null);    }    @Override    public void onLoadFinished(Loader loader, Cursor c) {        simpleCursorAdapter.swapCursor(c);    }    @Override    public void onLoaderReset(Loader loader) {        simpleCursorAdapter.swapCursor(null);    }

当数据库的数据变化的时候会自动回调onLoadFinished()来更新界面,同样这个方式也是由Activity来管理Cursor的,simpleCursorAdapter.swapCursor()会把之前的Cursor给close掉,并使用新的Cursor对象,onLoaderReset()就是由Activity中的performDestroy()来间接调用的,simpleCursorAdapter.swapCursor(null);被调用后就关闭了Cursor,这个方式获取Cursor是在子线程中,加载完成后会回调onLoadFinished()方法,不会阻塞UI线程,提高了流畅度,另外当Configuration发生变化是可以重用Cursor,不需要去重新获取Cursor,提高了效率,强烈的推荐大家在今后的开发中,使用这种方式。
好了,SimpleCursorAdapter的使用就说到这里,大家有什么疑问或者建议请给我留言!!!
最后给出一个参考demo https://github.com/takeyuweb/android-CursorLoaderSample 是个日本人写的,大家可以参照着看,我的部分代码也是来自于它

更多相关文章

  1. Android(安卓)HandlerThread用法
  2. 详解Android轻量型数据库SQLite
  3. Android(安卓)自定义RecyclerView.OnScrollListener,实现上拉分页
  4. android中的surface原理
  5. 获取web服务器xml数据
  6. Android(安卓)Data Binding 技术
  7. Android(安卓)Studio单元测试
  8. Android(安卓)NDK学习笔记3-入门案例篇
  9. android发现之旅之ViewRootImpl,Activity,Window,DecorView之间

随机推荐

  1. android中textView周围显示图片
  2. Android架构知识
  3. 粘贴复制Android复制和粘贴的实现
  4. Android Studio修改apk命名
  5. Android 文件存储--内部存储的例子
  6. Android AOSP输入法(LatinIME)大写判断分
  7. android的文件操作。(未整理完成)
  8. Android sub project list
  9. 【Android 界面效果4】android背景选择器
  10. Android:getWritableDatabase/getReadabl