AndroidLoader15.docx
- 文档编号:26193888
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:16
- 大小:39.70KB
AndroidLoader15.docx
《AndroidLoader15.docx》由会员分享,可在线阅读,更多相关《AndroidLoader15.docx(16页珍藏版)》请在冰豆网上搜索。
AndroidLoader15
1.Loader异步装载器认知:
1.1Loader的概念:
APILoaders
Loader装载器从android3.0开始引进。
它使得在activity或fragment中异步加载游标集合型的数据变得简单。
当成批显示数据的时候,为了使用户体验更好,需要进行异步装载。
也就是说,让未显示数据的ListView等UI组件或控件先显示,【避免出现白屏】的尴尬现象,同时在后台下载数据,等下载完成后再更新ListView组件。
这样尽管用户不会立刻看到数据,但是也不至于网络速度缓慢或服务器响应不及时而造成假死现象。
(请联想我们在ListView网络异步下载时先生成一个数据长度为0的List
1.2装载器具有如下特性:
1.2.1它们对每个Activity和Fragment都有效;
1.2.2他们提供了异步加载数据的能力;
1.2.3它拥有一个数据改变通知机制,当数据源做出改变时会及时通知。
也就是可以监听数据源,一旦数据源发生变化,Loader会感知这些变化;
1.2.4当Cursor发生变化时,会自动加载数据,因此并不需要再重新进行数据查询。
1.2.5android设计Loader的初衷是想让大家像CursorLoader的做法一样,通过loader去维护数据,每次启动loader时先检查有没有旧的数据并把旧的数据先deliver给用户,然后再考虑要不要重新加载新的数据。
1.3装载器API概述:
在使用装载器时,会涉及很多类和接口们,在下表中对它们总结一下:
Class/Interface
说明
LoaderManager
一个抽像类,关联到一个Activity或Fragment,管理一个或多个装载器的实例。
这帮助一个应用管理那些与Activity或Fragment的生命周期相关的长时间运行的的操作。
最常见的方式是与一个CursorLoader一起使用,然而应用是可以随便写它们自己的装载器以加载其它类型的数据。
每个activity或fragment只有一个LoaderManager。
但是一个LoaderManager可以拥有多个装载器。
LoaderManager.LoaderCallbacks
一个用于客户端与LoaderManager交互的回调接口。
例如,你使用回调方法onCreateLoader()来创建一个新的装载器。
Loader(装载器)
一个执行异步数据加载的抽象类。
它是加载器的基类。
你可以使用典型的CursorLoader,但是你也可以实现你自己的子类。
一旦装载器被激活,它们将监视它们的数据源并且在数据改变时发送新的结果。
AsyncTaskLoader
提供一个AsyncTask来执行异步加载工作的抽象类。
CursorLoader
AsyncTaskLoader的子类,它查询ContentResolver然后返回一个Cursor。
这个类为查询cursor以标准的方式实现了装载器的协议,它的游标查询是通过AsyncTaskLoader在后台线程中执行,从而不会阻塞界面。
使用这个装载器是从一个ContentProvider异步加载数据的最好方式。
相比之下,通过fragment或activity的API来执行一个被管理的查询就不行了。
1.4类目录结构:
1.4.1、API11中开始加入Loader:
java.lang.Object
↳android.content.Loader
↳android.content.AsyncTaskLoader
子类:
java.lang.Object
↳android.content.Loader
↳android.content.AsyncTaskLoader
↳android.content.CursorLoader
1.4.2、为了兼容1.6以下版本:
java.lang.Object
↳android.support.v4.content.Loader
↳android.support.v4.content.AsyncTaskLoader
子类:
java.lang.Object
↳android.support.v4.content.Loader
↳android.support.v4.content.AsyncTaskLoader
↳android.support.v4.content.CursorLoader
2.ListView相关的适配器:
2.1复习ArrayAdapter=>List
2.2BaseAdapter=>List
2.3SimpleAdapter(Day08)=》
////mDataAdapter=newSimpleAdapter(
//MainActivity.this,
//data,
//resource,
//from,
//to);
2.4SimpleCursorAdapter简易游标适配器,用于把游标数据自动填充到
adapter=newSimpleCursorAdapter(this,
R.layout.list_item,null,
newString[]{"_id","display_name"},
newint[]{R.id.tv_id,R.id.tv_name},
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
3.Loader异步装载器的使用流程:
3.1流程概述
第1步获取LoaderManager的实例=》利用activity提供的getLoaderManager()获取实例;
第2步initLoader利用初始化=>调用loaderManager实例的initLoader初始化
第3步实现回调=》实现initLoader中LoaderCallbacks接口的回调
第3.1创建=》在接口onCreateLoader中,创建并返回一个Loader
第3.2更新并显示数据=》在接口onLoadFinished()中,利用适配器的swapCursor函数把数据源重新更新到适配中,并自动刷新界面
第3.3复位重置=》在接口onLoaderReset中,利用适配器的swapCursor,把空数据重新更新到数据其中,并自动触发重新加载。
3.2流程步骤中的几个主要函数与参数的含义
3.2.1initLoader()方法来初始化;
原型:
initLoader(intid,Bundleargs,LoaderCallbacks
参数1id:
一个唯一ID来标志装载器
参数2args:
可选的参数,用于装载器初始化时
参数3callback:
一个LoaderManager.LoaderCallbacks的实现。
被LoaderManager调用以报告装载器的事件。
3.2.2initLoader()保证一个装载器被初始化并激活.它具有两种可能的结果:
3.2.2.1如果ID所指的装载器已经存在,那么这个装载器将被重用;
3.2.2.2如果装载器不存在,initLoader()就触发LoaderManager.LoaderCallbacks中的回调方法onCreateLoader()。
这是实例化并返回一个新Loader的地方。
3.2.3Loader对应的ListView配套的数据适配器必须是SimpleCursorAdapter。
同时SimpleCursorAdapter构造时,第三个参数Cursor设置为null,最后一个参数:
flags必须是:
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER。
3.2.3、自定义Loader中几个注意点
3.2.3.1自定义Loader作为onCreateLoader()的返回值(也就是说onCreateLoader()方法必须返回自定义Loader的实例);
3.2.3.2自定义Loader要继承于AsyncTaskLoader
3.2.3.3要在onStartLoading中调用forceLoad()才能依次调用下一个即将执行的方法。
在loadInBackground()方法中执行数据库查询,返回Cursor;
3.2.3.4在deliverResult()方法中执行跟适配器交换数据的操作,例如:
adapter.swapCursor(data)。
由于跟initLoader中回调方法onLoadFinished含义相同。
所以是根据需要选择是否重写。
3.3补充原Day15内容
3.3.1电话号码本的URI地址:
RawContacts.CONTENT_URI;
3.3.2CursorLoader游标自动装载器原型
CursorLoader(Contextcontext,Uriuri,String[]projection,Stringselection,String[]selectionArgs,StringsortOrder)
3.4核心代码示例(如何调用手机中的用户电话号码,请在手机中测试)
3.4.1代码示例
MainActivity=>onCreate(...){
......
lv=(ListView)findViewById(R.id.lv);
adapter=newSimpleCursorAdapter(this,
R.layout.list_item,null,
newString[]{"_id","display_name"},
newint[]{R.id.tv_id,R.id.tv_name},
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lv.setAdapter(adapter);
//用于管理Loader对象
LoaderManagerloaderManager=getLoaderManager();
//3个参数:
//①.id:
用来唯一的标示一个loader;
//②.args:
在构建loader对象的时候,也就是在调用loader的构造方法的时候,会调用的一个可选的参数;
//③.LoaderCallbacks:
就是我们要实现的回调方法
loaderManager.initLoader(1,null,this);
}
@Override
publicLoader
//本本部分是第Day15~Day16中的内容,临时调整
//电话号码本联系人的URI
Uriuri=RawContacts.CONTENT_URI;
//CursorLoader(Contextcontext,Uriuri,String[]projection,String//selection,String[]selectionArgs,StringsortOrder)
returnnewCursorLoader(this,
uri,
newString[]{"_id","display_name"},
null,null,null);
}
@Override
publicvoidonLoadFinished(Loader
adapter.swapCursor(data);
}
@Override
publicvoidonLoaderReset(Loader
adapter.swapCursor(null);
}
......
3.4.2添加电话号码本读权限
name="android.permission.READ_CONTACTS"/> 3.4.3额外观察 当电话号码本电话增加、减少、修改时的有无变化 4.AsyncTaskLoader的使用 4.1AsyncTaskLoader概念 AsyncTaskLoader顾名思义,就是AsyncTask+Loader,具有AsyncTask功能的Loader。 其使用方法跟AsyncTask一样,通过子类实现。 其在源代码定义为: publicabstractclassAsyncTaskLoader 子类使用时的定义通常为: classXXXTaskLoaderextendsAsyncTaskLoader 4.2通过示例来讲述,示例需要求 把上述例子中的loaderManager.initLoader.onCreateLoader(intid,Bundleargs){returnnewCursorLoader(.....)}中的CursorLoader替换为AsyncTaskLoader的子类。 4.3修改代码示例如下: 4.3.1需要新补充的几个函数 4.3.1.1forceLoad()强制加载数据 4.3.1.2Day15的函数 //得到一个内容提供者的解析者 ContentResolverresolver=getContentResolver(); //解析者执行的查询语句; resolver.query() 4.3.2子类MyTaskLoader的源码 staticclassMyTaskLoaderextendsAsyncTaskLoader publicMyTaskLoader(Contextcontext){ super(context); } @Override protectedvoidonStartLoading(){ super.onStartLoading(); //强制加载数据 forceLoad(); } //Calledonaworkerthreadtoperformtheactualload //andtoreturntheresultoftheloadoperation //这个方法,实在工作线程中执行的.在这个方法中会查询数据,并返回一个Cursor @Override publicCursorloadInBackground(){ //查询数据库 //Uriuri=RawContacts.CONTENT_URI;//两种方式都可以 Uriuri=Uri.parse("content: //com.android.contacts/raw_contacts"); returnresolver.query(uri,newString[]{"_id","display_name"},null,null,null); } } 4.3.3loaderManager中的替换部分 原内容 loaderManager.initLoader.onCreateLoader(intid,Bundleargs){returnnewCursorLoader(.....)}; 替换为 loaderManager.initLoader.onCreateLoader(intid,Bundleargs){returnnewMyLoader(this)}; 5.小综合的案例 5.1需求 在菜单的ActionBar中嵌入UI组件SearchView,通过SearchView的setOnQueryTextListener监视用户的输入,然后根据输入的内容从电话号码本中查找所有符合条件的用户显示到ListView中,并在菜单中提供进入系统的联系人列表Activity。 5.2思路: 5.2.1第1步, 准备好界面+ListView+ListView的EmptyView+内嵌SearchView的菜单项+能实现电话列表跳转的普通菜单项。 5.2.2第2步, 在选项菜单创建时,找到菜单项中内嵌的SearchView,设置其 setOnQueryTextListener监听器,在回调onQueryTextChange中,利用getLoaderManager().restartLoader(XXX)初始并重新开始一个Loader,并把监听器中捕获到的字符串封装到Bundle中,在restartLoader中通过参数形式传递到回调中;因为每次用户输入内容变化都需要重启一个Loader,因此放弃前面的initLoader; 5.2.3第3步, 在回调onCreateLoader中,记录传递的输入字符串,并new一个MyTaskLoader的实例,同时把封装有用户输入的Bundle通过构造传递给MyTaskLoader的实例。 5.2.4第4步, 在MyTaskLoader的loadInBackground中,通过resolver的查询语句,获取符合条件的用户记录的Cursor,并返回。 5.2.5第其它步骤, 剩余其它步骤,参照上述的其它例子即可。 5.3示例的核心代码: 5.3.1Java代码部分 publicclassMainActivityextendsActivityimplementsLoaderCallbacks privateListViewmLv; privateTextViewtvEmpty; privateSimpleCursorAdapteradapter; privatestaticContentResolverresolver; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLv=(ListView)findViewById(R.id.lv); tvEmpty=(TextView)findViewById(R.id.tv_empty); resolver=getContentResolver(); //loader对象初始化 getLoaderManager().initLoader(1,null,this); adapter=newSimpleCursorAdapter(this, R.layout.list_item,null, newString[]{"_id","display_name"}, newint[]{R.id.tv_id,R.id.tv_name}, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); mLv.setAdapter(adapter); //设置ListView的空视图 mLv.setEmptyView(tvEmpty); } @Override publicbooleanonCreateOptionsMenu(Menumenu){ getMenuInflater().inflate(R.menu.main,menu); MenuItemitem=menu.findItem(R.id.action_search); //得到一个搜索视图 SearchViewsearchView=(SearchView)item.getActionView(); //在搜索框中,监听用户的搜索动作 searchView.setOnQueryTextListener(newOnQueryTextListener(){ //当用户提交搜索请求的时候调用该方法 @Override publicbooleanonQueryTextSubmit(Stringquery){ returnfalse; } //当用户在搜索框中不断的改变文字的时候调用 //newText: 用户在搜索框中输入的文字 @Override publicbooleanonQueryTextChange(StringnewText){ Bundlebundle=newBundle(); bundle.putString("searchWord",newText); //利用LoaderManager中的restartLoader,重新加载新数据 //注意参数bundle的流转 getLoaderManager().restartLoader(1,bundle,MainActivity.this); returnfalse; } }); returntrue; } @Override publicbooleanonOptionsItemSelected(MenuItemitem){ switch(item.getItemId()){ caseR.id.action_look: //查看联系人,进入联系人列表 Intentintent=newIntent(); intent.setAction("com.android.contacts.action.LIST_CONTACTS"); startActivity(intent); break; default: break; } returnsuper.onOptionsItemSelected(item); } @Override publicLoader //注意参数bundle的流转 returnne
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- AndroidLoader15