Android 关于LoaderManager.LoaderCallbacks这个类

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wwdlss/article/details/50331153

从Android3.0开始,Android SDK提供了Loader技术,使用Loader技术可以很容易进行数据的异步加载。Loader技术为我们提供的核心类有:

    LoaderManager :可以通过Activity或者的Fragment的getLoaderManager()方法得到LoaderManager,用来对Loader进行管理一个Activity或者Fragment只能有一个LoaderManager。
    LoaderManager.LoaderCallbacks :用于同LoaderManager进行交互,可以在其中创建Loader对象。
    AsyncTaskLoader :抽象类,可以进行异步加载数据的Loader,貌似内部也是通过AsynTask实现的,可以通过继承它构建自己的Loader,也可以使用现有的子类,例如异步查询数据库可以使用CursorLoader。

使用Loader一般可以经过以下步骤:

   1、初始化Loader,可以使用initLoader(intid, Bundle args, LoaderManager.LoaderCallbackscallback);方法进行初始化。
id:标识Loader的ID,一个Activity或者Fragment只能有一个LoaderManager,但可以有多个Loader,通过ID区 分。在新建Loader时,如果发现已经有相同ID的Loader就会复用该Loader,而不会重新创建。
args:传给新建Loader的参数。 

Callback:回调接口。


   2、实现LoaderManager.LoaderCallbacks中的方法,LoaderManager.LoaderCallbacks中需要实现的方法有:
publicLoader onCreateLoader(int id, Bundle args):创建新的Loader,id为LoaderID,如果已经有相同ID的Loader就会复用该Loader,而不会重新创建。 args为初始化时传递的参数。该方法开始异步查询,并返回一个泛型类,如果是查询数据库可以返回一个CursorLoader,可以返回自定义的Loader。public voidonLoadFinished(Loader loader, D data):异步查询结束的会调用这个方法,并返回查询结果 data。public void onLoaderReset(Loader loader): 当调用Loader.reset()将Loader数据清空时,但在 系统销毁Loader时会自动调用Loader.reset()方法,我们一般不需要手动调用,只需要在onLoaderReset方法中,将使用Loader的移除。

3、使用 restartLoader(intid, Bundle args, LoaderManager.LoaderCallbacks callback)方法进行数据更新,和初始化一个,如果有相同id的Loader存在,会复用Loader,并清空原有Loader中的数据,如果没有就新建一个。这个方法一般使用在需要更新数据时,例如下面例子中,在搜索关键改变时,需要调用这个方法,从新异步查询数据。


下面一个例子使用CursorLoader查询联系人名字,并显示在界面中,在ActionBar上放置了一个SearchView可以根据联系人姓名关键字查询联系人。

一、布局文件(就一个listview):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView 
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</RelativeLayout>

二、menu.xml (actionbar 显示的菜单)
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.loadercallbackstest.MainActivity" >

    <item  
        android:id="@+id/action_search"  
        android:icon="@drawable/ic_menu_search"  
        android:actionViewClass="android.widget.SearchView"  
        android:showAsAction="ifRoom|collapseActionView"  
        android:title="@string/action_search" >  
        
    </item>

</menu>

三、Mainactivity

public class MainActivity extends Activity implements OnQueryTextListener {

	private String filterName=null;//搜索关键字
	private ListView lv;//列表
	private SimpleCursorAdapter adapter;//用来绑定游标得到的数据(适配器)
	private MyLoaderCallback callBack = new MyLoaderCallback();//LoaderCallback回调
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv = (ListView) findViewById(R.id.lv);
        adapter =new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2,
                null, new String[]{ContactsContract.Contacts.DISPLAY_NAME}, new int[]{android.R.id.text1},0);
        lv.setAdapter(adapter);
        initMyLoader();
        
    }
    
    
    /**
     * 初始化 Loader
     */
    private void initMyLoader(){
    	getLoaderManager().initLoader(0, null, callBack);
    }
    
    
    /**
     * @author Wu LoaderCallback
     *
     */
    private class MyLoaderCallback implements LoaderManager.LoaderCallbacks<Cursor> {

		@Override
		public Loader<Cursor> onCreateLoader(int id, Bundle args) {
			Uri uri = null;
	        String[] pro=new String[]{ ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.Contacts._ID};
	        if(TextUtils.isEmpty(filterName)){
	            uri= ContactsContract.Contacts.CONTENT_URI;
	        }else{
	            uri=Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI,Uri.encode(filterName));
	        }
	        //创建Loader对象,开始异步加载数据
	        return new CursorLoader(MainActivity.this, uri, pro, null, null, null);
		}

		@Override
		public void onLoadFinished(android.content.Loader<Cursor> loader,
				Cursor data) {
			adapter.swapCursor(data);
		}

		@Override
		public void onLoaderReset(android.content.Loader<Cursor> loader) {
			adapter.swapCursor(null);
		}
    	
    } 
    
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
        searchView .setOnQueryTextListener(this);
        return true;
    }


	@Override
	public boolean onQueryTextSubmit(String query) {
		return false;
	}


	@Override
	public boolean onQueryTextChange(String newText) {
		filterName=newText;
        //使用新的Loader(清空旧的数据)
        getLoaderManager().restartLoader(0,null,callBack);
		return false;
	}
  
}


四、最后记得在配置文件添加权限(这里我把有关电话的都写上了)

<uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
    <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
    <uses-permission android:name="android.permission.READ_CALL_LOG"/>
    <uses-permission android:name="android.permission.CALL_PHONE"/>

五、运行效果




六、总结

加载器的使用就是重写三个回调函数,并在加载完时设置Adapter的Cursor,使用Loader之后,只要数据源发生变化,就会自动调用onLoadFinished(),此时listview也会自动刷新。总之LoaderManager.LoaderCallbacks这个类这很多地方都可以用到 。异步加载网络图片啊一些需要异步操作的都可以使用他。


七、免积分下载demo:点击这里





猜你喜欢

转载自blog.csdn.net/wwdlss/article/details/50331153
今日推荐