Loader在Android3.0引进,它让异步加载数据变得容易。
特征:
1.在Activity、Fragment中都可以使用
2.Loader可以提供异步加载数据
3.监视数据源的变化,当数据源发生变化的时候,会传递新的数据
4.当loader重建的时候,会自动链接到最后一个Loader的cursor数据上,而不去进行重新查找。
在app中使用Loader的时候,可能使用到的类和接口:
LoaderManager:这是一个抽象类,关联在Activity、Fragment上,管理一个或多个Loader,帮助app管理耗时操作在Activity、Fragment的生命周期过程中。最常和CursorLoader一块使用。每一个Activity或Fragment只有一个FragmentManager对象。一个FragmentManager可以管理多个Loader
LoaderManager.LoaderCallbacks:和LoaderManger关联在一起的回调接口。onCreateLoader()会调方法,创建Loader对象。
Loader:抽象类,异步加载数据。主要使用CursorLoader。监视数据源的变化,当数据源发生改变的时候,传递新的数据内容。
AsyncTaskLoader:抽象的,提供了一个AsyncTask
CursorLoader:是AsyncTaskLoader的子类,使用ContentResolver查找数据,返回Cursor。加载Cursor数据的时候操作在非UI线程,so,不会阻塞UI线程。该类是查找ContentProvider提供出来的数据的最好的方式。
LoaderManager:用它实例化Loader--》cursorLoader
使用Loader:
1.Activity、Fragment
2.LoaderManager的实例
3.CursorLoader在后台加载数据--》ContentProvider
4.LoaderManager.LoaderCallbacks实现
5.需要展示数据的:SimpleCursorAdapter
6.数据源:ContentProvider
在一个Activity、Fragment中,只有一个LoaderManager实例。
需要在Activity的onCraete方法中或者是Fragment的onActivityCreated方法中实例化Loader对象:
getLoaderManager().initLoader(0,null, this);
public class MainActivity extends Activity implements LoaderCallbacks<Cursor>,OnQueryTextListener{
private TextView tv;
private ListView lv;
private SimpleCursorAdapter cursorAdapter;
private String filterName=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView) findViewById(R.id.tv);
tv.setText("请稍候");
cursorAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_2, null, new String[]{ContactsContract.Contacts.DISPLAY_NAME}, new int[]{android.R.id.text1},0);
lv=(ListView) findViewById(R.id.lv);
lv.setAdapter(cursorAdapter);
//初始化Loader
//参数1:实例化Loader数据加载的id
//参数2:传递参数onCreateLader()方法的第二个参数
//参数3:回调接口
getLoaderManager().initLoader(0, null, this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main,menu);
SearchView v= (SearchView) menu.findItem(R.id.menu_search).getActionView();
v.setOnQueryTextListener(this);
return true;
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Uri uri;
String [] pro = new String[]{ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.Contacts._ID};
if(TextUtils.isEmpty(filterName)){
uri=ContactsContract.Contacts.CONTENT_URI;
}
else{
//给当前的Uri最后追加一个 数字或字符串
uri=Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI, Uri.encode(filterName));
}
//创建Loader对象,开始异步加载数据
return new CursorLoader(this, uri, pro, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
//得到异步加载数据,更新Adapter
//交换Cursor,就是把之前已经有的Cursor交换掉,用data,所以起到一个更新的作用
cursorAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
//移除adapter使用的Loader,系统会释放不再使用的Loader
cursorAdapter.swapCursor(null);
}
@Override
public boolean onQueryTextSubmit(String query) {
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
filterName = newText;
getLoaderManager().restartLoader(0, null, this);
return false;
}
}
menu_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity" >
<item
android:id="@+id/menu_search"
android:actionViewClass="android.widget.SearchView"
android:showAsAction="ifRoom|collapseActionView"
android:title="搜索"
tools:ignore="AppCompatResource">
</item>
</menu>
效果图: