android CursorLoader用法介绍

原文:


http://www.jb51.net/article/37767.htm

http://write.blog.csdn.net/postedit?ref=toolbar


android CursorLoader用法介绍


工作内容集中到Contact模块,这个应用查询数据的地方很多,其使用了CursorLoader这个工具大大简化了代码复杂度。android自3.0提供了Loader机制,当时google的API只是简单的介绍了一下没有给出用法,大家很少有关注。后来因为重度模型下的性能优化,R&D的朋友发现这个东西非常给力,这才开始注意到这个强大的工具。CursorLoader是Loader的子类,可以说是Loader的升级版。这篇小结以loader为基础说明,弄懂原理之后也就明白了CursorLoader。
先说说google官方对Loader的介绍Loader对activity和fragment可用;Loader可以移步加载数据;loader自己会监视数据源的变化并且会主动上报;当发生配置上的变化,重新生成的loader会自动连接到变化前的cursor,这样就避免再查一次数据库。咱自己在补充一个,loader能在应用不使用查询到的资源时候,自动将其释放。这些介绍自android3.0之后,就可以从官方文档山看到。当时依据这些并不知道怎么样使用,看了framework侧的实现之后还是一头雾水:咋用。现在来看这就像activity一样,我们可以不知道framework中怎么样开始一个activity怎么样管理activity但是我们仍然能很好的使用activity;对于CursorLoader,我们大可以不必知道framework中的原理,只要利用好google提供的接口LoaderManager以及为其注册事件的接口LoaderManager.LoaderCallbacks就可以实现我们需要的功能。
实际上CursorLoader完全可以看成一个很牛的查询工具,拥有一般的查询不具备的能力,如上面的google官方介绍。我们通过LoaderManager.LoaderCallbacks接口来在适当的时候提供查询配置或者利用查询返回到的结果。使用好CursorLoader重在实现好LoaderManager.LoaderCallbacks接口。看下这个接口里面提供了哪些方法:


[java]


复制代码 代码如下:



public interface LoaderCallbacks<D> {
    public Loader<D> onCreateLoader(int id, Bundle args);
    public void onLoadFinished(Loader<D> loader, D data);
    public void onLoaderReset(Loader<D> loader);
}

    public interface LoaderCallbacks<D> {
        public Loader<D> onCreateLoader(int id, Bundle args);
        public void onLoadFinished(Loader<D> loader, D data);
        public void onLoaderReset(Loader<D> loader);
    }

   
第一个方法onCreateLoader是创建Loader时候调用,是为了提供查询的配置,比如查询地址,查询项目等。这个方法会在loader初始化也就是注册这个接口的时候调用,常见代码如下:


[java]
getLoaderManager().initLoader(0, null, this);


    getLoaderManager().initLoader(0, null, this);第一个参数是当前activity里面loader的ID,一般为0,第二个参数一般置null,第三个就是实现了LoaderManager.LoaderCallbacks的类,一般就是当前activity。这句代码执行之后就会执行onCreateLoader,然后去查询,查询结束之后就会执行onLoadFinished,做你需要做的事情。一般就在第二个方法里面利用查询结果,如传递到一个adapter进行显示。第三个方法onLoaderReset是在我们的配置发生变化的,使用restartLoader(int , Bundle ,LoaderManager.LoaderCallbacks<D>)方法重新初始化loader之后调用的,一般是用来释放对前面loader查询到的结果引用。对Loader的使用只需要在重新初始化之前去除引用,退出activity时候不需要关闭cursor释放资源。
到这里loader的用法就已经说完了,记住上面三个方法的用处,在适当的地方初始化loader,我们就可以利用Loader实现我们的需要。现在说说Loader和CursorLoader的关系:Loader是核心,其已经实现了基本功能;AsyncTaskLoader继承自Loader,主要任务就是将耗时操作从主线程中剥离出来;CursorLoader继承自AsyncTaskLoader,是泛型类的一个具体类,也是我们最常用Loader。
Loader的到来给android应用开发带来了很大的方便。在数据加载的性能优化中有一项分布加载,没有Loader之前,我们需要将查询实现在AsyncQueryHandler类里面,在其onQueryComplete回调方法里面触发后续查询。上面这些需要自定义一个内部类,一堆代码,搞得晕乎乎的。%>_<% 用来Loader只要在onLoadFinished里面增加一些判断即可,很方便。


CursorLoader类取代managerQurey方法

之前我们在给ListView填充数据时,都会用SimpleCursorAdapter适配器,自然而然会需要Cursor这个参数
那这个参数是怎么来的呢,同志们都知道Cursor cursor=managerQuery();可以得到。
可是,发现很多同志也发现:
The method managedQuery(Uri, String[], String, String[], String) from the type Activity is deprecated。
android官方文档推荐用CursorLoader类来取代.
我找了很久,很多同志也有在找,但都没有实际或成功的例子。
我后来在google上面找到一个大神的描述,并把描述形成代码
希望能对大家有帮助,也欢迎指正。
我的源码是在项目中国水系的代码上修改过来的,感谢原作者!
部份主要代码如下:
public class RiverSystemActivity extends FragmentActivity{
       
        private ListView riverListView;
        private CursorAdapter adapter;
        private CursorLoader cursorLoader;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_river_system);

        riverListView=(ListView) findViewById(R.id.riverList);
        initRiverCursorLoader();
        initRiverListView();
    }

        //use CursorLoader to adapter listView data
    private void initRiverCursorLoader() {
                // TODO Auto-generated method stub
            //First, create (and set up) the CursorAdapter.the cursor is null
                adapter=new SimpleCursorAdapter(this, R.layout.row, null,
                                new String[]{
                                RiverContentProvider.NAME,RiverContentProvider.INTRODUCTION},
                                new int[]{R.id.riverName,R.id.riverIntroduction},
                                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
               
                //Next, initialize the loader.
                getSupportLoaderManager().initLoader(0,null,
                                new LoaderCallbacks<Cursor>(){

                                        /**The LoaderManager calls onCreateLoader(int id, Bundle args).
                                         * returns a subclass of the Loader<Cursor>
                                         * This Cursorloader will perform the initial query and will update itself
                                         * when the data set changes.
                                         */
                                        @Override
                                        public Loader<Cursor> onCreateLoader(int id, Bundle arg1) {
                                                Log.d("listview","on create loader");
                                                cursorLoader=new CursorLoader(
                                                                RiverSystemActivity.this,
                                                                RiverContentProvider.CONTENT_URI,new String[]{
                                                                RiverContentProvider._ID,
                                                                RiverContentProvider.NAME,
                                                                RiverContentProvider.INTRODUCTION},null,null,null
                                                                );
                                                return cursorLoader;
                                        }

                                        /**
                                         * The queried cursor is passed to the adapter.
                                         * Immediately after the CursorLoader is instantiated and returned ,
                                         * the CursorLoader performs the initial query on a separate thread and a cursor is returned.
                                         * When the CursorLoader finishes the query, it returns the newly queried cursor to the LoaderManager,
                                         * which then passes the cursor to the onLoadFinished method.
                                         * From the documentation, "the onLoadFinished method is called
                                         * when a previously created loader has finished its load."
                                         * @param arg0
                                         * @param cursor
                                         */
                                        @Override
                                        public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
                                                Log.d("listview","on create finished");
                                                adapter.swapCursor(cursor);
                                               
                                        }

                                        @Override
                                        public void onLoaderReset(Loader<Cursor> arg0) {
                                                Log.d("listview","on create reset");
                                                adapter.swapCursor(null);
                                        }
                       
                });
                riverListView.setAdapter(adapter);
                riverListView.setOnItemClickListener(new OnItemClickListener(){

                        @Override
                        public void onItemClick(AdapterView<?> parent, View view,
                                        int position, long id) {
                                Log.d("listItem", ">>" + id);
                                Intent intent=new Intent();
                                intent.setClass(RiverSystemActivity.this, RiverDetailActivity.class);
                                intent.putExtra(GlobalValues.RIVER_ID, id);
                                startActivity(intent);
                               
                        }
                       
                });               
        }   

    //use Cursor to adapter listView data
    private void initRiverListView() {
                Cursor cursor = managedQuery(RiverContentProvider.CONTENT_URI, null,
                                null, null, null);
                adapter=new SimpleCursorAdapter(this,R.layout.row,cursor,
                                new String[]{
                                RiverContentProvider.NAME,RiverContentProvider.INTRODUCTION},
                                new int[]{R.id.riverName,R.id.riverIntroduction},
                                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
                riverListView.setAdapter(adapter);
               
                riverListView.setOnItemClickListener(new OnItemClickListener(){

                        @Override
                        public void onItemClick(AdapterView<?> parent, View view,
                                        int position, long id) {
                                Log.d("listItem", ">>" + id);
                                Intent intent=new Intent();
                                intent.setClass(RiverSystemActivity.this, RiverDetailActivity.class);
                                intent.putExtra(GlobalValues.RIVER_ID, id);
                                startActivity(intent);
                               
                        }
                       
                });
        }
}


        initRiverCursorLoader();
        initRiverListView();
两个方法都可以,第一个是CursorLoader类实现,第一个是用managerQuery实现的
最关键的地方是:
getSupportLoaderManager().initLoader(0,null,
                                new LoaderCallbacks<Cursor>(){}

实现这个接口,会有三个方法要实现
其中public Loader<Cursor> onCreateLoader(int id, Bundle arg1)
这个方法返回的是Loader<Cursor>
我一直在想怎么把Loader<Cursor>转成cursor,这样我可以建立adapter,一直没有成功
可是实现上它的原理是Loader<Cursor>返回给LoaderManager,由LoaderManager
解析成Cursor cursor传递给查询结束方法
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
                                                Log.d("listview","on create finished");
                                                adapter.swapCursor(cursor);
                                               
                                        }
由adapter.swap(cursor)自动完成所有数据填充功能
当然这里的adapter要事先定义好,只是cursor is null.




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值