android适配器SimpleCursorAdapter的使用以及最后一个参数的作用
2016-01-28 18:44
771 查看
在android开发中,我们经常用SimpleCursorAdapter来绑定数据库里面的数据,很多人在使用这个类的时候并不知道具体怎么样来用,或者说还有很多疑问,比如最后一个参数该怎么写,这个cursor什么时候关闭,是怎么管理cursor的等等。
在android的不同的版本中,对SimpleCursorAdapter的使用方法是不同的,我们先来看下SimpleCursorAdapter构造方法,SimpleCursorAdapter有两个构造方法,其实可以归并为一个构造方法,我们看下构造方法的说明:
我们看最后一个参数flags,它有两个值可以选择分别为:
首先我们来看没有flag参数或者参数为
正如字面意思,FLAG_AUTO_REQUERY会自动查询如果数据库中的数据发生了变化以实时反映到界面上来,这样使用有一个问题,查询数据是发生在UI线程中,会造成卡顿的现象,甚至出现ANR异常,取决于手机的配置及数据的大小,这也是android3.0及以上放弃的原因,尽管如此,我们还是有些问题需要来理解。
一般来说我们使用Cursor需要close,但是在这里我们并没close,那么是怎么处理的呢,原理是Activity自己帮我处理的,大家看我是使用managedQuery来获取Cursor对象的,在这个方法中
用getContentResolver().query()获取到Cursor对象以后,使用startManagingCursor()把Cursor对象加入到Activity中管理。我们看下startManagingCursor方法
以Cursor构建了一个ManagedCursor对象,并加入到一个类型为ArrayList的mManagedCursors容器里面去了,在Activity中的onDestroy()方法中,我们看到下面的代码
没错,从mManagedCursors循环取出所有的ManagedCursor对象,并关闭里面的Cursor,在Activity中的performRestart()方法,我们看到如下代码
我们看到了mCursor.requery()方法,这个方法是用来重新查询数据,在Activity重新开始的时候,performRestart()方法是Activity重新开始过程会被调用的方法。这下大家明白Activity是怎么管理Cursor的吧!注意如果大家在使用这个的时候一定要managedQuery()方法来获取Cursor,不然Cursor没被Activity管理,会游离在外,有可能会出现游标未关闭异常,大家最好不用这种方法了,android已经废弃!!!
然后我们看使用第二个参数来构建SimpleCursorAdapter对象即Flag为CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER,这是android3.0及以上的做法,我们需要使用到CursorLoader来加载数据了
在回调方法中写上对应的代码
当数据库的数据变化的时候会自动回调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 是个日本人写的,大家可以参照着看,我的部分代码也是来自于它
在android的不同的版本中,对SimpleCursorAdapter的使用方法是不同的,我们先来看下SimpleCursorAdapter构造方法,SimpleCursorAdapter有两个构造方法,其实可以归并为一个构造方法,我们看下构造方法的说明:
我们看最后一个参数flags,它有两个值可以选择分别为:
CursorAdapter.FLAG_AUTO_REQUERY和
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER,另外一个构造方法就是少了最后一个参数,默认被设置为
CursorAdapter.FLAG_AUTO_REQUERY。
首先我们来看没有flag参数或者参数为
CursorAdapter.FLAG_AUTO_REQUERY的情况,这种是在android3.0以下版本中才使用的,在分为android3.0及以上的版本中,已经被废弃了,是不建议使用的,我们还是来说明下使用方法
[code] 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对象的,在这个方法中
[code]@Deprecated public 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方法
[code] @Deprecated public void startManagingCursor(Cursor c) { synchronized (mManagedCursors) { mManagedCursors.add(new ManagedCursor(c)); } }
以Cursor构建了一个ManagedCursor对象,并加入到一个类型为ArrayList的mManagedCursors容器里面去了,在Activity中的onDestroy()方法中,我们看到下面的代码
[code] // 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()方法,我们看到如下代码
[code] synchronized (mManagedCursors) { final int N = mManagedCursors.size(); for (int i=0; i<N; 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来加载数据了
[code] 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);
在回调方法中写上对应的代码
[code] @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { return new CursorLoader(this, Persons.CONTENT_URI, null, null, null, null); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor c) { simpleCursorAdapter.swapCursor(c); } @Override public void onLoaderReset(Loader<Cursor> 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 是个日本人写的,大家可以参照着看,我的部分代码也是来自于它
相关文章推荐
- Android Barrier
- Android 日常
- Android 开发绕不过的坑:你的 Bitmap 究竟占多大内存?
- Android Studio 提高代码质量——Inspact Code
- 【开源中国Android客户端】源码分析(一) 启动
- Android 中dp,px,dpi以及sp的区别
- Genymotion - 强大好用高性能的 Android 模拟器 (在电脑流畅运行APK安卓软件游戏的利器)
- android相关下载
- android安全:forceStopPackage对android的Alarm的影响
- Android Studio插件分享
- Material Design动画(一)
- Win 10 下 android studio显示 Intel haxm无法安装,以及VT-X和hyper-x的冲突问题
- Win 10 下 android studio显示 Intel haxm无法安装,以及VT-X和hyper-x的冲突问题
- Android实现从底部弹出的Dialog(二)
- Android Studio gradle的基本用法
- Android布局文件中的四种单位
- 使用Android Studio发布私有库到仓库中心
- 如何用AndroidStudio关联github导入项目
- Android实现从底部弹出的Dialog(一)
- Android代码内存优化建议-Android资源篇