loader(加载器)

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

1.LoaderManager:

可以通过Activity或者的Fragment的getLoaderManager()方法得到LoaderManager,用来对Loader进行管理,一个Activity或者Fragment只能有一个LoaderManager。

2.LoaderManager.LoaderCallbacks:

用于同LoaderManager进行交互,可以在其中创建Loader对象。

3.AsyncTaskLoader:

抽象类,可以进行异步加载数据的Loader,貌似内部也是通过AsynTask实现的,可以通过继承它构建自己的Loader,也可以使用现有的子类,例如异步查询数据库可以使用CursorLoader。

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

1、初始化Loader,可以使用 initLoader(intid, Bundle args, LoaderManager.LoaderCallbacks callback); 方法进行初始化。

id:
标识Loader的ID,一个Activity或者Fragment只能有一个LoaderManager,但可以有多个Loader,通过ID区 分。在新建Loader时,如果发现已经有相同ID的Loader就会复用该Loader,而不会重新创建。
args:
传给新建Loader的参数。
Callback:
回调接口。

initLoader()方法调用确保了一个loader会被初始化以及激活 它有两种可能的后果:

如果赋予loader的ID已经存在,那么上一个被创建的loader就会被重用
如果赋予loader的ID不存在, initLoader()就会触发 LoaderManager.LoaderCallbacks的onCreateLoader()方法。 这里就是你实例化并返回一个新loader的地方。

2、实现LoaderManager.LoaderCallbacks中的方法,LoaderManager.LoaderCallbacks中需要实现的方法有:

onCreateLoader(int id, Bundle args):

当你试图操作一个loader的时候,(例如通过initLoader()), 会检查被赋予唯一ID的loader是否存在。如果不存在,它会触发LoaderManager.LoaderCallbacks的onCreateLoader()方法。 这是你创建新loader的地方。一般来说被创建的都是CursorLoader,但是你可以实现你自己的Loader子类。
在本例中,onCreateLoader() 回调方法创建了一个CursorLoader。你必须使用它的构造方法建造这个 CursorLoader,构造方法需要向 which ContentProvider执行一次查询的完整信息作为参数。它还需要:尤其地,它还需要:
uri — 要获取的内容的URI。
projection — 返回的列组成的列表,传入null将会返回所有列,但是效率很低。
selection — 一个声明返回哪些行的过滤器,被格式化成类似SQL中WHERE子句的形式(除了没有WHERE自己)。传入null将会返回给定URI的所有行。
selectionArgs — 你可能在Selection中包含一些‘?’,他们将会被selectionArgs的值给替换掉,顺序与它们在selection中出现的顺序一致。 这些值被约束为String类型
sortOrder — 怎样给这些行排顺序,被格式化为类似SQL中ORDER BY子句的形式(除了没有ORDER自己)。传入null 将会使用默认的排序方式,可能是没有顺序。

onLoadFinished(Loader loader, D data):

异步查询结束的会调用这个方法,并返回查询结果 data。

onLoaderReset(Loader loader):

当调用Loader.reset()将Loader数据清空时,但在系统销毁Loader时会自动调用Loader.reset()方法,我们一般不需要手动调用,只需要在onLoaderReset方法中,将使用Loader的移除。

3、使用 restartLoader(intid,Bundleargs,LoaderManager.LoaderCallbacks callback)

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

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

Activity代码如下:

public static class CursorLoaderListFragment extends ListFragment
        implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {

    //这就是用来展示列表信息的Adapter。
    SimpleCursorAdapter mAdapter;

    //如果不是null,这就是当前的搜索过滤器。
    String mCurFilter;

    @Override public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        //如果没有数据,就给控件一些文本去显示。  
        //在真正的应用中,信息来自应用资源。
        setEmptyText("No phone numbers");

        //我们在action bar中显示一个菜单项。
        setHasOptionsMenu(true);

        //创建一个新的adapter,我们将用它来显示加载的数据。
        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);

        //准备loader, 重连到一个已存在的loader,
        //或者启动一个新的loader。
        getLoaderManager().initLoader(0, null, this);
    }

    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        //放置一个action bar用于搜索。
        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) {
        //action bar上的搜索文本改变的时候被调用。 
        //更新搜索过滤器,并且重启loader用当前的过滤器
        //来做新的查询。
        mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
        getLoaderManager().restartLoader(0, null, this);
        return true;
    }

    @Override public boolean onQueryTextSubmit(String query) {
        //不必关心这个方法。
        return true;
    }

    @Override public void onListItemClick(ListView l, View v, int position, long id) {
        // Insert desired behavior here.
        Log.i("FragmentComplexList", "Item clicked: " + id);
    }

    //我们想获取的联系人中的行数据。
    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<Cursor> onCreateLoader(int id, Bundle args) {
        //当需要创建一个新的loader时被调用。 
        //本例中仅有一个loader,所以我们不必关心ID的问题。
        //首先,根据我们当前是否正在过滤,
        //选择base URI来使用。
        Uri baseUri;
        if (mCurFilter != null) {
            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                    Uri.encode(mCurFilter));
        } else {
            baseUri = Contacts.CONTENT_URI;
        }

        //现在创建并返回一个CursorLoader,
        //它将会为被显示的数据创建一个Cursor。
        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<Cursor> loader, Cursor data) {
        //把新的cursor换进来。  (框架将会在我们返回的时候
        //管理旧cursor的关闭事宜。)
        mAdapter.swapCursor(data);
    }

    public void onLoaderReset(Loader<Cursor> loader) {
        //当最后一个Cursor进入onLoadFinished()的时候被调用。
        //cursor将要被关闭, 我们应该确保
        //不再使用它。
        mAdapter.swapCursor(null);
    }
}

API

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值