1、Loader,加载器
实现异步加载数据的功能,类似于AsyncTask
监听数据源的改变,实时刷新控件(ListView)
将耗时的操作放在子线程中,防止ANR
适应场景:
适配器需要使用CursorAdapter
数据源来源于数据库(可以是自己app下的数据库,也可以是其他app的数据库,可以通过ContentProvider向外暴露数据)
Loader必须使用在Activity或Fragment中
2、使用步骤
a:使用Activity实现接口LoaderCallbacks,并重写3个方法
b:通过上下文获得LoaderManager,通过manager启动Loader
manager。initLoader(id,args,calllback)
EditText的监听事件:etName.addTextChangedListener(new TextWatcher(){});
SearchView的监听事件:sv.setOnQueryTextListener(new OnQueryTextListener(){});
案例一:
public class MainActivity extends Activity implements LoaderCallbacks<Cursor> {
private ListView lv;
private SimpleCursorAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.listView1);
adapter = new SimpleCursorAdapter(this, R.layout.item, null,
new String[] { "display_name", "data1" }, new int[] {
R.id.textView1, R.id.textView2 },
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lv.setAdapter(adapter);
// 通过上下文获得Loader的管理器
LoaderManager manager = getLoaderManager();
// id:用来唯一标示Loader
// args:传值使用的参数,在构建时或重启时
// callback:要实现的回调方法
manager.initLoader(1, null, this);
}
// 创建Loader
// id:Loader唯一的标示
// args:调用者可以给Loader传递消息,接收参数
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// TODO Auto-generated method stub
return new CursorLoader(getApplicationContext(),
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] { "_id", "display_name", "data1" }, null, null,
null);
//return后面可以替换成自定义的AsyncLoader
}
// onLoadFinished在onCreateLoader方法执行结束之后调用
// loader:onCreateLoader的返回值
// data:是Loader对象自带的Cursor
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// TODO Auto-generated method stub
// 当Loader数据加载完成,将数据设置给Adapter,之后在ListView中显示
adapter.swapCursor(data);
}
// 当创建的Loader重置(重启)时调用该方法
// 通常将上面查询获得Cursor设置为不可用
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// TODO Auto-generated method stub
adapter.swapCursor(null);// 清除旧数据
}
}
案例二:
// 给EditText添加文本改变的监听
etName.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
Log.i("TAG", "--onTextChanged" + s);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
Log.i("TAG", "--beforeTextChanged" + s);
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
Log.i("TAG", "--afterTextChanged" + s);
//
Bundle bundle = new Bundle();
bundle.putString("key", s.toString());
// 重启Loader并传递参数(查询条件)
getLoaderManager().restartLoader(1, bundle, MainActivity.this);
}
});
案例三:自定义AsyncLoader
// AsyncTaskLoader 有一个内部类实现了AsyncTask
// 查询并加载数据
static class MyLoader extends AsyncTaskLoader<Cursor> {
public MyLoader(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onStartLoading() {//这一步是自己手动写的且必须写,不然没有数据
// TODO Auto-generated method stub
super.onStartLoading();
// 强制加载数据
forceLoad();
}
// 在工作线程执行,查询数据,返回Cursor
@Override
public Cursor loadInBackground() {
// TODO Auto-generated method stub
Cursor cursor = resolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] { "_id", "display_name", "data1" }, null,
null, null);
return cursor;
}
}
案例四:
// SearchView添加事件
mSearchView.setOnQueryTextListener(new OnQueryTextListener() {
// 键盘输入,回车开始执行,调用该方法
@Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
Bundle bundle = new Bundle();
bundle.putString("key", query);
getLoaderManager().restartLoader(1, bundle,MainActivity.this);
return false;
}
// 内容改变时调用该方法
@Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
return false;
}
});
在自定义的AsyncLoader中如何处理传进来的参数
public class MyCursorLoader extends AsyncTaskLoader<Cursor> {
private Bundle args;
public MyCursorLoader(Context context, Bundle args) {
super(context);
// TODO Auto-generated constructor stub
this.args = args;
}
@Override
protected void onStartLoading() {
// TODO Auto-generated method stub
super.onStartLoading();
forceLoad();
}
@Override
public Cursor loadInBackground() {
// TODO Auto-generated method stub
ContentResolver resolver = getContext().getContentResolver();
if (args == null) {
return resolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] { "_id", "display_name", "data1" }, null,
null, null);
} else {
String where = "display_name like ?";
String[] whereArgs = { "%" + args.getString("key") + "%" };
return resolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] { "_id", "display_name", "data1" }, where,
whereArgs, null);
}
}
}