打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Android之数据库异步加载利器

英文文档出处:http://developer.android.com/guide/components/loaders.html

Loaders,中文可理解为“加载器”,在Android3.0中新增。从字面含义可见其功能,即提供数据加载。特别地,加载数据的方式为异步。它具有以下特点:

  • Loaders用于所有的Activity和Fragment;
  •  提供异步数据装载机制;
  • 监控他们的来源数据变化情况,在数据发生变化的时候传递新的结果;
  • 自动重连到最后一个数据加载器游标,因此不需要重新查询数据


如何在应用中使用Loaders

使用Loaders的先决条件:

  • 需要一个Activity 或者 Fragmnet
  • 一个LoaderManager实例
  • 一个用于加载数据的的CursorLoader对象(依赖于ContentProvider)
  • 一个LoaderManager.LoaderCallbacks的实现类.
  • 一个数据展现适配器,比如SimpleCursorAdapter
  • 一个数据源,比如ContentProvider

启动数据加载器Loaders

LoaderManager管理者一个Activity或者Fragment中的一个或多个Loader实例,每个Activity或者Fragment只有对应一个LoaserManager。
         一般在Activity的onCreate方法或者Fragment的onActivityCreated方法中初始化一个Loader:
getLoaderManager().initLoader(0, null, this);
参数:

1、  第一个参数:0 为Loader的唯一标识ID;
2、  第二个参数: 为Loader的构造器可选参数,这里为null;
3、  第三个参数:this,这里表示当前Activity对象或者Fragment对象,提供给LoaderManager对象进行数据汇报。
InitLoader()方法保证了Loader初始化及对象激活,执行这个方法有2个可能的结果:

1、  如果ID存在,则重复利用;
2、  如果ID不存在,则出发LoaderManager.LoaderCallbacks的onCreateLoader()方法新创建一个Loader并返回;


不管在什么情况下,只有Loader状态发生了变化,与之关联的LoaderManager.LoaderCallbacks实现类都会被告知;

你可能注意到了,initLoader返回的Loader对象并未与任何变量关联,那是因为LoaderManager有自动的Loader管理功能;LoaderManager在必要的时候自动启动及停止数据加载操作,并且维护者Loader的状态;这就意味着,你很少直接与Loader进行交互。一般地,使用LoaderManager.LoaderCallbacks的onCreateLoader()方法去干预数据加载的过程中的特殊事件。


如何重启数据加载器Loaders

在上面创建Loaders时,如果ID不存在则创建,否则使用旧的Loader,但有些时候,我们需要清理掉旧的数据重新开始。
使用restartLoaser()可以做到。比如,SearchView.OnQueryTextListener的实现类,在查询条件发生改变时重启Loaders,以便获取最新的查询结果。

  1. public boolean onQueryTextChanged(String newText) {  
  2.   
  3.     // Called when the action bar search text has changed.  Update  
  4.   
  5.     // the search filter, and restart the loader to do a new query  
  6.   
  7.     // with this filter.  
  8.   
  9.     mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;  
  10.   
  11.     getLoaderManager().restartLoader(0nullthis);  
  12.   
  13.     return true;  
  14. }  

如何使用LoaderManager的回调方法

LoaderManager.LoaderCallbacks 接口是客户端与LoaderManager进行交互的腰带。
Loader ,特别是CursorLoader,期望在停止状态后保存它们的状态。这样的话,用户在交互过程中,就避免了数据的重新加载而导致UI卡死的局面。使用回调函数,就可以知道什么时候去创建一个新的Loader,并且告知应用程序什么时候停止使用Loader加载的数据。

回调方法有:

  • onCreateLoader():根据给定的ID创建新的Loader;
  • onLoaderFinished():当Loader完成数据加载后调用;
  • onLoaderReset():Loader重置,使之前的数据无效;
 
onCreateLoader使用实例:

  1. // If non-null, this is the current filter the user has provided.  
  2.   
  3. String mCurFilter;  
  4.   
  5. ...  
  6.   
  7. public Loader<Cursor> onCreateLoader(int id, Bundle args) {  
  8.   
  9.     // This is called when a new Loader needs to be created.  This  
  10.   
  11.     // sample only has one Loader, so we don't care about the ID.  
  12.   
  13.     // First, pick the base URI to use depending on whether we are  
  14.   
  15.     // currently filtering.  
  16.   
  17.     Uri baseUri;  
  18.   
  19.     if (mCurFilter != null) {  
  20.   
  21.         baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,  
  22.   
  23.                   Uri.encode(mCurFilter));  
  24.   
  25.     } else {  
  26.   
  27.         baseUri = Contacts.CONTENT_URI;  
  28.   
  29.     }  
  30.   
  31.    
  32.   
  33.     // Now create and return a CursorLoader that will take care of  
  34.   
  35.     // creating a Cursor for the data being displayed.  
  36.   
  37.     String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("  
  38.   
  39.             + Contacts.HAS_PHONE_NUMBER + "=1) AND ("  
  40.   
  41.             + Contacts.DISPLAY_NAME + " != '' ))";  
  42.   
  43.     return new CursorLoader(getActivity(), baseUri,  
  44.   
  45.             CONTACTS_SUMMARY_PROJECTION, select, null,  
  46.   
  47.             Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");  
  48. }  

CursorLoader(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)构造器参数解释:
Context:上下文,这里是Activity对象或者Fragment对象
Uri:内容检索地址
Projection:要显示的列,传null表示查询所有的列
Selection:查询过滤语句,类似SQL WHERE ,传null,表示查询所有
selectionArgs:查询参数,替换在selection中定义的  ?
sortOrder:排序定义,类似SQL ORDER BY


完整的实例

  1. public static class CursorLoaderListFragment extends ListFragment  
  2.   
  3.         implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {  
  4.   
  5.    
  6.   
  7.     // This is the Adapter being used to display the list's data.  
  8.   
  9.     SimpleCursorAdapter mAdapter;  
  10.   
  11.    
  12.   
  13.     // If non-null, this is the current filter the user has provided.  
  14.   
  15.     String mCurFilter;  
  16.   
  17.    
  18.   
  19.     @Override public void onActivityCreated(Bundle savedInstanceState) {  
  20.   
  21.         super.onActivityCreated(savedInstanceState);  
  22.   
  23.    
  24.   
  25.         // Give some text to display if there is no data.  In a real  
  26.   
  27.         // application this would come from a resource.  
  28.   
  29.         setEmptyText("No phone numbers");  
  30.   
  31.    
  32.   
  33.         // We have a menu item to show in action bar.  
  34.   
  35.         setHasOptionsMenu(true);  
  36.   
  37.    
  38.   
  39.         // Create an empty adapter we will use to display the loaded data.  
  40.   
  41.         mAdapter = new SimpleCursorAdapter(getActivity(),  
  42.   
  43.                 android.R.layout.simple_list_item_2, null,  
  44.   
  45.                 new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },  
  46.   
  47.                 new int[] { android.R.id.text1, android.R.id.text2 }, 0);  
  48.   
  49.         setListAdapter(mAdapter);  
  50.   
  51.    
  52.   
  53.         // Prepare the loader.  Either re-connect with an existing one,  
  54.   
  55.         // or start a new one.  
  56.   
  57.         getLoaderManager().initLoader(0nullthis);  
  58.   
  59.     }  
  60.   
  61.    
  62.   
  63.     @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {  
  64.   
  65.         // Place an action bar item for searching.  
  66.   
  67.         MenuItem item = menu.add("Search");  
  68.   
  69.         item.setIcon(android.R.drawable.ic_menu_search);  
  70.   
  71.         item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);  
  72.   
  73.         SearchView sv = new SearchView(getActivity());  
  74.   
  75.         sv.setOnQueryTextListener(this);  
  76.   
  77.         item.setActionView(sv);  
  78.   
  79.     }  
  80.   
  81.    
  82.   
  83.     public boolean onQueryTextChange(String newText) {  
  84.   
  85.         // Called when the action bar search text has changed.  Update  
  86.   
  87.         // the search filter, and restart the loader to do a new query  
  88.   
  89.         // with this filter.  
  90.   
  91.         mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;  
  92.   
  93.         getLoaderManager().restartLoader(0nullthis);  
  94.   
  95.         return true;  
  96.   
  97.     }  
  98.   
  99.    
  100.   
  101.     @Override public boolean onQueryTextSubmit(String query) {  
  102.   
  103.         // Don't care about this.  
  104.   
  105.         return true;  
  106.   
  107.     }  
  108.   
  109.    
  110.   
  111.     @Override public void onListItemClick(ListView l, View v, int position, long id) {  
  112.   
  113.         // Insert desired behavior here.  
  114.   
  115.         Log.i("FragmentComplexList""Item clicked: " + id);  
  116.   
  117.     }  
  118.   
  119.    
  120.   
  121.     // These are the Contacts rows that we will retrieve.  
  122.   
  123.     static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {  
  124.   
  125.         Contacts._ID,  
  126.   
  127.         Contacts.DISPLAY_NAME,  
  128.   
  129.         Contacts.CONTACT_STATUS,  
  130.   
  131.         Contacts.CONTACT_PRESENCE,  
  132.   
  133.         Contacts.PHOTO_ID,  
  134.   
  135.         Contacts.LOOKUP_KEY,  
  136.   
  137.     };  
  138.   
  139.     public Loader<Cursor> onCreateLoader(int id, Bundle args) {  
  140.   
  141.         // This is called when a new Loader needs to be created.  This  
  142.   
  143.         // sample only has one Loader, so we don't care about the ID.  
  144.   
  145.         // First, pick the base URI to use depending on whether we are  
  146.   
  147.         // currently filtering.  
  148.   
  149.         Uri baseUri;  
  150.   
  151.         if (mCurFilter != null) {  
  152.   
  153.             baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,  
  154.   
  155.                     Uri.encode(mCurFilter));  
  156.   
  157.         } else {  
  158.   
  159.             baseUri = Contacts.CONTENT_URI;  
  160.   
  161.         }  
  162.   
  163.    
  164.   
  165.         // Now create and return a CursorLoader that will take care of  
  166.   
  167.         // creating a Cursor for the data being displayed.  
  168.   
  169.         String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("  
  170.   
  171.                 + Contacts.HAS_PHONE_NUMBER + "=1) AND ("  
  172.   
  173.                 + Contacts.DISPLAY_NAME + " != '' ))";  
  174.   
  175.         return new CursorLoader(getActivity(), baseUri,  
  176.   
  177.                 CONTACTS_SUMMARY_PROJECTION, select, null,  
  178.   
  179.                 Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");  
  180.   
  181.     }  
  182.   
  183.    
  184.   
  185.     public void onLoadFinished(Loader<Cursor> loader, Cursor data) {  
  186.   
  187.         // Swap the new cursor in.  (The framework will take care of closing the  
  188.   
  189.         // old cursor once we return.)  
  190.   
  191.         mAdapter.swapCursor(data);  
  192.   
  193.     }  
  194.   
  195.    
  196.   
  197.     public void onLoaderReset(Loader<Cursor> loader) {  
  198.   
  199.         // This is called when the last Cursor provided to onLoadFinished()  
  200.   
  201.         // above is about to be closed.  We need to make sure we are no  
  202.   
  203.         // longer using it.  
  204.   
  205.         mAdapter.swapCursor(null);  
  206.   
  207.     }  
  208. }  










本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
android loader fragment
Android实现获取本机中所有图片
Android 深入理解Loader机制 让APP轻装上阵
Android Cursor自动更新的实现和原理 · KOHOH的技术博客
Android4开发入门经典 之 第三部分:Activity
android怎么读取短信的threads表
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服