zoukankan      html  css  js  c++  java
  • LoaderManager使用详解(二)---了解LoaderManager

    了解LoaderManager

    这篇文章将介绍LoaderManager类,这是该系列的第二篇文章。
    二:了解LoaderManager

    注意:
    要了解这一LoaderManager这部分知识,要求对Loaders如何工作有基本了 解。Loaders的实现将在下一篇文章中涵盖。现在你只需要将Loaders看成一个简单、字包含的对象。该对象特性包括:1.在一个单独线程载入数 据;2.监测底层数据源,当探测到有改变时就更新或者重新查询。了解上面的Loader相关内容就足以了解本文内容了。下文所有的Loaders假设 100%正确。

    LoaderManager是什么?


    简单的理解是,LoaderManager用来负责管理与Activity或者 Fragment联系起来的一个或多个Loaders对象。每个Activity或者Fragment都有唯一的一个LoaderManager实例,用 来启动、停止、保持、重启、关闭它的Loaders。这些事件有时直接在客户端通过调用initLoader()/restartLoader() /destroyLoader()函数来实现。通常这些事件通过主要的Activity/Fragment声明周期事件来触发,而不是手动(当然也可以手 动调用)。比如,当一个Activity关闭时(destroyed),改活动将指示它的LoaderManager来销毁并且关闭它的 Loaders(当然也会销毁并关闭与这些Loaders关联的资源,比如Cursor)。
    LoaderManager并不知道数据如何装载以及何时需要装载。相反 地,LoaderManager只需要控制它的Loaders们开始、停止、重置他们的Load行为,在配置变换(比如横竖屏切换)时保持loaders 们的状态,并提供一个简单的接口来获取load结果到客户端中。从上面的行为可以看到,LoaderManager是一个比现在过时的 startManagingCursor方法更加智能和通用的方法。在Activity的声明周期状态轮转中,比较两种管理数据的方法,可以发现 LoaderManager方法有下面几个方面更胜一筹:

    1. startManagingCursor管理Cursors,而LoaderManager管理Loader<D>对象。 Loader<D>是一个模板类,D是一个包含了需要载入数据的类。也就是说,数据源并不必须是Cursor,它可以是List、 JSONArray。。。任何类。LoaderManager与它包含的数据内容解耦了,所以更加灵活。

    2. 调用startManagingCursor会导致Activity在已经加入管理的Cursor上调用requery()方法。在第一篇文章中提到过, 在UI线程执行requery()方法代价非常高。相反的是,Loader<D>的子类会异步载入(译者注:另外再开一个线程,就叫异步 了。)数据,所以使用LoaderManager永远不会产生阻塞UI线程的情况。

    3. startManagingCursor在配置变化(例如横竖屏切换)时,并不会保持Cursor的状态。麻烦的是,每次Activity由于配置变化 (比如,简单的横竖屏切换),都会导致Cursor下回并且被重新查询。LoaderManager就智能多了,当配置变化时,它会保持它里面的 Loader们的状态,所以并不需要重新查询数据。

    4. LoaderManager提供无缝的数据监测。任何时候,当Loader的数据源改变,LoaderManager将会从对应的Loader上面接收到 一个新的同步载入数据,并将更新数据返回给客户端(注意:仅当Loader被正确实现,LoaderManager才会接收到这些数据变化通知。我们将会 在该系列的第三篇文章讨论自定义Loaders的实现)。

    如果你觉得上面很难,我也并不会强调她。上面的内容最重要的是LoaderManager让 你的生活更容易。LoaderManager为你初始化、管理、销毁Loaders,减少了代码复杂度和与Activity或者Fragment生命周期 相关的bug。更多地,与LoaderManager交互需要实现三个简单的回调方法,我们在下一节将讨论 LoaderManager.LoaderCallbacks<D>。

    实现LoaderManager.LoaderCallbacks<D>接口

    LoaderManager.LoaderCallbacks<D>接口 LoaderManager用来向客户返回数据的方式。每个Loader都有自己的回调对象供与LoaderManager进行交互。该回调对象在实现 LoaderManager中地位很高,告诉LoaderManager如何实例化Loader(onCreateLoader),以及当载入行为结束或 者重启(onLoadFinished或者onLoadReset)之后执行什么操作。大多数情况,你需要把该接口实现为组件的一部分,比如说让你的 Activity或者Fragment实现LoadManager.LoaderCallbacks<D>接口。
    1. public class SampleActivity extends Activity implements LoaderManager.LoaderCallbacks<D> {  
    2.   
    3.   public Loader<D> onCreateLoader(int id, Bundle args) { ... }  
    4.   
    5.   public void onLoadFinished(Loader<D> loader, D data) { ... }  
    6.   
    7.   public void onLoaderReset(Loader<D> loader) { ... }  
    8.   
    9.   /* ... */  
    10. }  

    一旦实现该接口,客户端将回调对象(本例中为“this”)作为LoaderManager的initLoader函数的第三个参数传输。
    总的来说,实现回调接口非常直接明了。每个回调方法都有各自明确的与LoaderManager进行交互的目的:
    1. onCreateLoader是一个工厂方法,用来返回一个新的Loader。LoaderManager将会在它第一次创建Loader的时候调用该方法。
    2. onLoadFinished方法将在Loader创建完毕的时候自动调用。典型用法是,当载入数据完毕,客户端(译者注:调用它的Activity之类 的)需要更新应用UI。客户端假设每次有新数据的时候,新数据都会返回到这个方法中。记住,检测数据源是Loader的工作,Loader也会执行实际的 同步载入操作。一旦Loader载入数据完成,LoaderManager将会接受到这些载入数据,并且将将结果传给回调对象的 onLoadFinished方法,这样客户端(比如Activity或者Fragment)就能使用该数据了。

    3. 最后,当Loader们的数据被重置的时候将会调用onLoadReset。该方法让你可以从就的数据中移除不再有用的数据。

    在下一节中,我们将讨论Android初学者们经常问到的问题:如何从过时的Managed Cursor转移到更强大的LoaderManager来?

    从Managed Cursor转移到LoaderManager

    下面的代码跟上一篇文章的代码实现的功能类似。当然,不同就是改成使用 LoaderManager来实现。CursorLoader确保所有的查询都是异步执行,这确保了我们不会阻塞UI线程。更进一 步,LoaderManager在Activity全生命周期管理CursorLoader,当配置转换时保持它的数据。处理每次新数据在回调接口的 onLoadFinished方法中的载入。这样Activity可以很自由的使用查询结果。

    1. public class SampleListActivity extends ListActivity implements  
    2.     LoaderManager.LoaderCallbacks<Cursor> {  
    3.   
    4.   private static final String[] PROJECTION = new String[] { "_id", "text_column" };  
    5.   
    6.   // The loader's unique id. Loader ids are specific to the Activity or  
    7.   // Fragment in which they reside.  
    8.   private static final int LOADER_ID = 1;  
    9.   
    10.   // The callbacks through which we will interact with the LoaderManager.  
    11.   private LoaderManager.LoaderCallbacks<Cursor> mCallbacks;  
    12.   
    13.   // The adapter that binds our data to the ListView  
    14.   private SimpleCursorAdapter mAdapter;  
    15.   
    16.   @Override  
    17.   public void onCreate(Bundle savedInstanceState) {  
    18.     super.onCreate(savedInstanceState);  
    19.   
    20.     String[] dataColumns = { "text_column" };  
    21.     int[] viewIDs = { R.id.text_view };  
    22.   
    23.     // Initialize the adapter. Note that we pass a 'null' Cursor as the  
    24.     // third argument. We will pass the adapter a Cursor only when the  
    25.     // data has finished loading for the first time (i.e. when the  
    26.     // LoaderManager delivers the data to onLoadFinished). Also note  
    27.     // that we have passed the '0' flag as the last argument. This  
    28.     // prevents the adapter from registering a ContentObserver for the  
    29.     // Cursor (the CursorLoader will do this for us!).  
    30.     mAdapter = new SimpleCursorAdapter(this, R.layout.list_item,  
    31.         null, dataColumns, viewIDs, 0);  
    32.   
    33.     // Associate the (now empty) adapter with the ListView.  
    34.     setListAdapter(mAdapter);  
    35.   
    36.     // The Activity (which implements the LoaderCallbacks<Cursor>  
    37.     // interface) is the callbacks object through which we will interact  
    38.     // with the LoaderManager. The LoaderManager uses this object to  
    39.     // instantiate the Loader and to notify the client when data is made  
    40.     // available/unavailable.  
    41.     mCallbacks = this;  
    42.   
    43.     // Initialize the Loader with id '1' and callbacks 'mCallbacks'.  
    44.     // If the loader doesn't already exist, one is created. Otherwise,  
    45.     // the already created Loader is reused. In either case, the  
    46.     // LoaderManager will manage the Loader across the Activity/Fragment  
    47.     // lifecycle, will receive any new loads once they have completed,  
    48.     // and will report this new data back to the 'mCallbacks' object.  
    49.     LoaderManager lm = getLoaderManager();  
    50.     lm.initLoader(LOADER_ID, null, mCallbacks);  
    51.   }  
    52.   
    53.   @Override  
    54.   public Loader<Cursor> onCreateLoader(int id, Bundle args) {  
    55.     // Create a new CursorLoader with the following query parameters.  
    56.     return new CursorLoader(SampleListActivity.this, CONTENT_URI,  
    57.         PROJECTION, null, null, null);  
    58.   }  
    59.   
    60.   @Override  
    61.   public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {  
    62.     // A switch-case is useful when dealing with multiple Loaders/IDs  
    63.     switch (loader.getId()) {  
    64.       case LOADER_ID:  
    65.         // The asynchronous load is complete and the data  
    66.         // is now available for use. Only now can we associate  
    67.         // the queried Cursor with the SimpleCursorAdapter.  
    68.         mAdapter.swapCursor(cursor);  
    69.         break;  
    70.     }  
    71.     // The listview now displays the queried data.  
    72.   }  
    73.   
    74.   @Override  
    75.   public void onLoaderReset(Loader<Cursor> loader) {  
    76.     // For whatever reason, the Loader's data is now unavailable.  
    77.     // Remove any references to the old data by replacing it with  
    78.     // a null Cursor.  
    79.     mAdapter.swapCursor(null);  
    80.   }  
    81. }  

    总结

    正如其名LoaderManager,它负责在Activity或者Fragment的生命 周期内管理Loader们。LoaderManager很简单,并且它的实现代码量通常很少。比较难的部分是实现Loaders,这个主题将在下一篇文章 中讨论:实现Loaders(三)(超链接)
  • 相关阅读:
    Java高并发8-计算机内存模式以及volatile,sychronized工作原理
    Java高并发7-inheritableThreadLocal实现父子线程变量同步原理
    Java高并发6-ThreadLocal内部各种方法实现原理
    Java高并发5-守护线程、ThreadLocal和死锁四个必要条件
    Java高并发4-解析volatile关键字
    AQS详解,并发编程的半壁江山
    Java 调用File的delete方法删除文件返回false
    Java 将文件夹打成压缩包 zip
    前端 文件夹上传 解决方案
    ORA-00904: "FILED_TYPE": 标识符无效
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4378908.html
Copyright © 2011-2022 走看看