android loaders,Android之Activity--Loaders

特性:

Available For Every Activity and Fragment

Asynchronous loading data

monitor source data and deliever new results when the content changes

reconnnect to the last loader's cursor.

Loader API Summary

LoaderManager, 抽象类,关联到Activity(or Fragment), 用于管理LoaderManager的实例。每个Activity或者Fragmente只拥有一个LoaderManager,但一个LoadManager可拥有多个loaders, 常用的有CursoLoader

LoaderManager.LoaderCallbacks, 接口类,用于Client与LoaderManager交互

Loader, 抽象类, 执行异步loading data, 具体类CursorLoader, 它会监视源文件,并在内容变化时传递变化结果

AsyncTaskLoader, 抽象Loader, 提供一个AsyncTask 以便执行任务。

CursorLoader, AsyncTaskLoader子类,查询ContentResolver 并返回Cursor。实现了Loader协议,并使用AsyncTaskLoader将任务放至后台进行处理。最好的异步加载数据 from ContentResolver的解决方案

Starting a Loader

1. onCreate()

getLoaderManaer().initLoader(int id, Bundle args, LoaderCallbacks callback)

其中

id设为0,标示loader, 若该id已被使用,则直接连接上使用该id的loader,否则create one.

args设为null, 无配置数据

callback 设为this, loadmanager将汇报loader event。

当检索条件改变,希望重新查询的时候,使用getLoaderManager().restartLoader(0, null, this);

具体initLoader所做工作,可看源码追踪的时序图。

2. Using the LoaderManager Callbacks

在实现LoaderManager.LoaderCallbacks接口时,三个方法必须实现:

- onCreateLoader() — 根据所给id 实例化loader and 返回一个新的loader

- onLoadFinished() — 数据加载完成时, 参数data即是返回的结果。

- onLoaderReset() — 当数据源更新时。

可在onLoadFinished方法中,发送EVENT至Handler,然后在Handler中处理数据刷新,更新UI等工作。

Tracking Source Code

当开发者在实现LoaderCallbacks接口的onCreateLoader()方法,返回CursorLoader实例时,

在LoadManager.LoadManagerImpl.LoaderInfo.start()方法中会调用

mLoader = mCallbacks.onCreateLoader(mId, mArgs);

这样就将我们CursorLoader的实例传入了LoaderInfo的实例中。

其中mCallbacks在LoaderInfo的构造方法中进行赋值,也就是传入我们实现的LoaderCallbacks接口的实例。

public LoaderInfo(int id, Bundle args, LoaderManager.LoaderCallbacks callbacks)

接下来会调用

mLoader.startLoading()

而Loader类的startLoading()方法会调用onStartLoading(),它是一个空方法。

CursorLoader 作为Loader的子类,重写了onStartLoading()方法,代码如下:

Java@Override

protected void onStartLoading() {

if (mCursor != null) {

deliverResult(mCursor);

}

if (takeContentChanged() || mCursor == null) {

forceLoad();

}

}

可见,当mCursor为空时,或者contentChanged时,都将调用forceLoad()。也即数据源更新时,CursorLoader会自动调用onLoadComplete(),所以开发者只需在此处发送事件给Handler,让其更新数据即可。

当mCursor不为空,则直接传递结果,此处将会调用onLoadFinish()方法,将数据传递给客户端onLoadComplete()。

具体代码流程如图所示。

bVkVHB

对于数据源更新,如何自动调用onLoadComplete()方法,简单来说,就是在进行onCreateLoader()方法中,会注册观察者,使其在数据更新时,将takeContentChanged()置为true。不再进行详细展开。

Example

Javapublic 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);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值