目录
1.加载器特征
用于每个 activity 和 fragment
支持异步加载数据。
监控其数据源并在内容变化时传递新结果。
2. loader api
3. 在应用中使用loader
主要步骤
activity 或 fragment
loadermanager 的实例
一个 cursorloader,用于加载由contentprovider 支持的数据。您也可以实现自己的 loader或 asynctaskloader 子类,从其他源中加载数据。
一个 loadermanager.loadercallbacks 实现。您可以使用它来创建新加载器,并管理对现有加载器的引用。
一种显示加载器数据的方法,如 simplecursoradapter。
使用 cursorloader 时的数据源,如 contentprovider。
3.1. 启动加载器
在 activity 的 oncreate() 方法或片段的onactivitycreated() 方法内初始化 loader
// prepare the loader. either re-connect with an existing one,
// or start a new one.
// 标识id + 构建时给加载器的可选参数 + loadermanager.loadercallbacks 实现
getloadermanager().initloader(0, null, this);
// 如果 id 指定的加载器已存在,则将重复使用上次创建的加载器。
// 如果 id 指定的加载器不存在,则 initloader() 将触发 loadermanager.loadercallbacks 方法 oncreateloader()
3.2. 重启加载器
public boolean onquerytextchanged(string newtext) {
// called when the action bar search text has changed. update
// the search filter, and restart the loader to do a new query
// with this filter.
mcurfilter = !textutils.isempty(newtext) ? newtext : null;
getloadermanager().restartloader(0, null, this);
return true;
}
3.3. 使用loadermanager回调
loadermanager.loadercallbacks 是一个支持客户端与loadermanager 交互的回调接口。
加载器(特别是 cursorloader)在停止运行后,仍需保留其数据。这样,应用即可保留 activity 或片段的 onstop()和 onstart() 方法中的数据。当用户返回应用时,无需等待它重新加载这些数据。您可使用 loadermanager.loadercallbacks 方法了解何时创建新加载器,并告知应用何时停止使用加载器的数据。
loadermanager.loadercallbacks 包括以下方法:
oncreateloader():针对指定的 id 进行实例化并返回新的 loader
onloadfinished():将在先前创建的加载器完成加载时调用
onloaderreset():将在先前创建的加载器重置且其数据因此不可用时调用
4. 实例: 访问用户联系人
public static class cursorloaderlistfragment extends listfragment
implements onquerytextlistener, loadermanager.loadercallbacks {
// this is the adapter being used to display the list's data.
simplecursoradapter madapter;
// if non-null, this is the current filter the user has provided.
string mcurfilter;
@override public void onactivitycreated(bundle savedinstancestate) {
super.onactivitycreated(savedinstancestate);
// give some text to display if there is no data. in a real
// application this would come from a resource.
setemptytext("no phone numbers");
// we have a menu item to show in action bar.
sethasoptionsmenu(true);
// create an empty adapter we will use to display the loaded data.
madapter = new simplecursoradapter(getactivity(),
android.r.layout.simple_list_item_2, null,
new string[] { contacts.display_name, contacts.contact_status },
new int[] { android.r.id.text1, android.r.id.text2 }, 0);
setlistadapter(madapter);
// prepare the loader. either re-connect with an existing one,
// or start a new one.
getloadermanager().initloader(0, null, this);
}
@override public void oncreateoptionsmenu(menu menu, menuinflater inflater) {
// place an action bar item for searching.
menuitem item = menu.add("search");
item.seticon(android.r.drawable.ic_menu_search);
item.setshowasaction(menuitem.show_as_action_if_room);
searchview sv = new searchview(getactivity());
sv.setonquerytextlistener(this);
item.setactionview(sv);
}
public boolean onquerytextchange(string newtext) {
// called when the action bar search text has changed. update
// the search filter, and restart the loader to do a new query
// with this filter.
mcurfilter = !textutils.isempty(newtext) ? newtext : null;
getloadermanager().restartloader(0, null, this);
return true;
}
@override public boolean onquerytextsubmit(string query) {
// don't care about this.
return true;
}
@override public void onlistitemclick(listview l, view v, int position, long id) {
// insert desired behavior here.
log.i("fragmentcomplexlist", "item clicked: " + id);
}
// these are the contacts rows that we will retrieve.
static final string[] contacts_summary_projection = new string[] {
contacts._id,
contacts.display_name,
contacts.contact_status,
contacts.contact_presence,
contacts.photo_id,
contacts.lookup_key,
};
public loader oncreateloader(int id, bundle args) {
// this is called when a new loader needs to be created. this
// sample only has one loader, so we don't care about the id.
// first, pick the base uri to use depending on whether we are
// currently filtering.
uri baseuri;
if (mcurfilter != null) {
baseuri = uri.withappendedpath(contacts.content_filter_uri,
uri.encode(mcurfilter));
} else {
baseuri = contacts.content_uri;
}
// now create and return a cursorloader that will take care of
// creating a cursor for the data being displayed.
string select = "((" + contacts.display_name + " notnull) and ("
+ contacts.has_phone_number + "=1) and ("
+ contacts.display_name + " != '' ))";
return new cursorloader(getactivity(), baseuri,
contacts_summary_projection, select, null,
contacts.display_name + " collate localized asc");
}
public void onloadfinished(loader loader, cursor data) {
// swap the new cursor in. (the framework will take care of closing the
// old cursor once we return.)
madapter.swapcursor(data);
}
public void onloaderreset(loader 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);
}
}