在android 开发中耗时操作,尽量不要在UI线程中执行,而contentResolver 访问数据的方式是在主线程中,在数据量繁琐的时候,我们可以采用loader方式访问其他应用程序提供的数据,只需让,Activity,或者fragment 实现loaderCallBack 接口,实现其中的三个方法即可,需要注意的是,在执行完,onCreateLoader()方法之后,的返回值,将作为onLoadFinsh()方法的一个参数,类似异步操作中的doInbackGround ()以及onPostActivity()方法,在开启loader 的时候,getloaderManger().initLoader(int id,Bundle args,LoaderCallbacks<Cursor> callback)三个参数,代码中解释如下
id A unique identifier for this loader. Can be whatever you want. Identifiers are scoped to a particular LoaderManager instance.
args Optional arguments to supply to the loader at construction. If a loader already exists (a new one does not need to be created), this parameter will be ignored and the last arguments continue to be used.
callback Interface the LoaderManager will call to report about changes in the state of the loader. Required.
可见id 对此loader 起标识作用,假设你对数据库进行更改,需要重新加载数据库中的值,可调用 getLoaderManager().resetLoader(int id,Bundle args,LoaderCallbacks<Cursor> callback),三个参数,此时你需要使用,与之前相同id ,Bundle中可以给 onCreateLoader(int id, Bundle args) 方法传值 代码如下:
package com.example.loaderapp;
import android.app.Activity;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.v4.widget.SimpleCursorAdapter;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
public class MainActivity extends Activity implements LoaderCallbacks<Cursor>{
//Loader 加载
/**
* content resolver 在主线程中使用的
*/
private ListView lv;
private SimpleCursorAdapter adapter;
private SearchView search;
// 这个 uri 是针对 raw_contacts 和 data 两张表连接查询的 注意是 两张
private Uri contactUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
private String[] columns = {"_id","display_name","raw_contact_id","data1"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.lv);
search = (SearchView) findViewById(R.id.search);
adapter = new SimpleCursorAdapter(this, R.layout.item_self,null,new String[]
{"display_name","data1"}, new int[]{R.id.tv_name,R.id.tv_phone},
SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lv.setAdapter(adapter);
//② 使用loader 加载数据 使用的 loader 的子类 CursorLoader
//a) 让activity 或 Fragment 实现一个接口 LoaderCallbacks
// ③得到loader 管理对象 initLoader 用于初始化 loader
getLoaderManager().initLoader(7, null, this); // 第一个参数 就是为了 标识 这个 loader 的 第二个参数 传递的参数 没有 就写 Null
search.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
//输入完了 执行这个方法
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
//输入的过程中执行该方法
//参数是用户输入的文本
//
Bundle args = new Bundle();
args.putString("key",newText);
// 重新启动 Loader
getLoaderManager().restartLoader(7, args, MainActivity.this);
return false;
}
});
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// 创建Loader Loader 和 resolver 区别 只是 一个主线程 一个子线程 他们是类似的
String where = null;
String[] whereArgs = null;
if(args!=null){
String data = args.getString("key");
where = "display_name like ? or data1 like ?";
//意思是 只要含有就查出来
whereArgs = new String[]{"%"+data+"%","%"+data+"%"};
}
return new CursorLoader(this, contactUri, columns, where, whereArgs, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
//loader 加载完数据执行 该方法 由主线程执行
adapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
//重置 Loader的时候执行 相当于
adapter.swapCursor(null);// 重新查询了 数据有变化了 重新用 loader 查询数据
}
}