zoukankan      html  css  js  c++  java
  • 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接口。看下这个接口里面提供了哪些方法:

        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初始化也就是注册这个接口的时候调用,常见代码如下:

        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里面增加一些判断即可,很方便。

    public class ListViewLoader extends ListActivity
            implements LoaderManager.LoaderCallbacks<Cursor> {
    
        // This is the Adapter being used to display the list's data
        SimpleCursorAdapter mAdapter;
    
        // These are the Contacts rows that we will retrieve
        static final String[] PROJECTION = new String[] {ContactsContract.Data._ID,
                ContactsContract.Data.DISPLAY_NAME};
    
        // This is the select criteria
        static final String SELECTION = "((" + 
                ContactsContract.Data.DISPLAY_NAME + " NOTNULL) AND (" +
                ContactsContract.Data.DISPLAY_NAME + " != '' ))";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            // Create a progress bar to display while the list loads
            ProgressBar progressBar = new ProgressBar(this);
            progressBar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                    LayoutParams.WRAP_CONTENT, Gravity.CENTER));
            progressBar.setIndeterminate(true);
            getListView().setEmptyView(progressBar);
    
            // Must add the progress bar to the root of the layout
            ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
            root.addView(progressBar);
    
            // For the cursor adapter, specify which columns go into which views
            String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};
            int[] toViews = {android.R.id.text1}; // The TextView in simple_list_item_1
    
            // Create an empty adapter we will use to display the loaded data.
            // We pass null for the cursor, then update it in onLoadFinished()
            mAdapter = new SimpleCursorAdapter(this, 
                    android.R.layout.simple_list_item_1, null,
                    fromColumns, toViews, 0);
            setListAdapter(mAdapter);
    
            // Prepare the loader.  Either re-connect with an existing one,
            // or start a new one.
            getLoaderManager().initLoader(0, null, this);
        }
    
        // Called when a new Loader needs to be created
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            // Now create and return a CursorLoader that will take care of
            // creating a Cursor for the data being displayed.
            return new CursorLoader(this, ContactsContract.Data.CONTENT_URI,
                    PROJECTION, SELECTION, null, null);
        }
    
        // Called when a previously created loader has finished loading
        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
            // Swap the new cursor in.  (The framework will take care of closing the
            // old cursor once we return.)
            mAdapter.swapCursor(data);
        }
    
        // Called when a previously created loader is reset, making the data unavailable
        public void onLoaderReset(Loader<Cursor> loader) {
            // This is called when the last Cursor provided to onLoadFinished()
            // above is about to be closed.  We need to make sure we are no
            // longer using it.
            mAdapter.swapCursor(null);
        }
    
        @Override 
        public void onListItemClick(ListView l, View v, int position, long id) {
            // Do something when a list item is clicked
        }
    }
  • 相关阅读:
    栈 队列 递归 算法的GO语言实现
    数组与链表算法
    树算法的GO语言实现
    排序算法的GO语言实现
    如何抵抗记忆的衰退
    C程序运行的背后(2)
    C程序运行的背后(1)
    Shell脚本:“syntax error:unexpected end of file”
    电线的粗细与电流的大小怎么算?电流的大小与电器的功率有什么关系? 如何根据电流的大小选择铜质电线的粗细
    Word2019发布文章到博客园
  • 原文地址:https://www.cnblogs.com/scarecrow-blog/p/4612828.html
Copyright © 2011-2022 走看看