Loaders

 

介绍在android3.0,Loaders 使异步导入数据在一个activity或fragment使用简单。Loaders特点:

1.      他们可以使用到每个activity和fragment。

2.      他们可以提供异步导入数据。

3.      他们监控他们的数据源并投递新的结果当内容改变时。

4.      他们自动重连接最后Loader的游标当被重新创建在一个配置修改,因此,他们不需要重新查询他们的数据。

 

LoaderAPI总结

这个多个类和接口被调用在使用loader在应用中。他们总结了这些在表中:

Class/Interface

Description

LoaderManager

An abstract class associated with an Activity or Fragment for managing one or more Loader instances. This helps an application manage longer-running operations in conjunction with the Activity orFragment lifecycle; the most common use of this is with a CursorLoader, however applications are free to write their own loaders for loading other types of data. 

There is only one
 LoaderManager per activity or fragment. But aLoaderManager can have multiple loaders.

LoaderManager.LoaderCallbacks

A callback interface for a client to interact with the LoaderManager. For example, you use the onCreateLoader() callback method to create a new loader.

Loader

An abstract class that performs asynchronous loading of data. This is the base class for a loader. You would typically use CursorLoader, but you can implement your own subclass. While loaders are active they should monitor the source of their data and deliver new results when the contents change.

AsyncTaskLoader

Abstract loader that provides an AsyncTask to do the work.

CursorLoader

A subclass of AsyncTaskLoader that queries the ContentResolver and returns a Cursor. This class implements the Loader protocol in a standard way for querying cursors, building on AsyncTaskLoader to perform the cursor query on a background thread so that it does not block the application's UI. Using this loader is the best way to asynchronously load data from a ContentProvider, instead of performing a managed query through the fragment or activity's APIs.

 

这些类和接口子上面表中基本的组件你使用实现一个加载器在你的应用中。你不需要所有的加载器你创建,但是你将总是需要一个引用对LoaderManager为了初始化一个加载器并且实现一个加载器类比如CursorLoader。这个会在接下来将展示你怎么使用类和接口在应用中。

 

使用加载器在应用中

1.      一个activity或者Fragment.

2.      一个LoaderManager实例

3.      一个CursorLoader来加载数据用ContentProvider.也许你可以实现你自己的类Loader或者AsyncTaskLoader来加载数据从一些另外的资源里。

4.      一个实现LoaderManaer.LoaderCallbacks。这个是你创建一个新的加载器并且管理你的应用已经存在的加载器。

5.      一个方式展示加载的数据像一个SimpleCursorAdapter。

6.      一个数据源,比如ContentProvider,当使用CursorLoader。

 

启动一个

 

LoaderManager管理一个或多个Loader实例在一个Activity或Fragment。这个只有一个LoaderManager在每个activity或fragment里。

 

你代表初始化一个Loader在一个Activity的onCreate()方法里或者在fragment的onActivityCreated()方法。你可以接下来做:

// Prepare the loader.  Eitherre-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0,null, this);

这个initLoader方法做接下来的参数:

1.      唯一的ID定义这个loader。在例子这个id为0。

2.      可选择参数支持加载在构造函数中。

3.      一个LoaderManager.LoaderCallbacks实现,哪个LoaderManager调用报告加载器事件。在例子中,本地类实现LoaderManager.LoaderCallbacks接口,所以这个通过一个本身的引用。

这个initLoader()调用确定这个加载器初始化并激活。他有两个结果:

1.      假如加载器指定被一个已经存在的id,最后创建的会恢复。

2.      假如指定被一个不存在的id,initLoader()触发LoaderManager.LoaderCallbacks方法onCreateLoader()。在这个你实现的代码中示例并返回一个新的加载器。更多的讨论在onCreateLoader部分。

 

在无论发生什么情况,这个LoaderManager.LoaderCallbacks实现了相关联的加载器,并且将被调用当加载器状态改变时。假如在某个时间调用当调用者在启动状态,并且这个请求加载已经存在并且产生数据,当系统调用onLoaderFinished马上,所以你必须马上准备为这个发生。看onLoaderFinished为更多的讨论在返回。

 

注意initLoader()方法返回这个加载器被创建,但是你不需要捕获一个对它的引用。LoaderManager自动管理生命周期。这个LoaderManager开始并停止加载当需要的时候,并且保留加载器的状态并联系内容。这就意味着,你很少直接的和加载器交互(虽然对一个例子很少使用加载器方法在fine-tune加载的行为,看LoaderThrottle例子)。你必须使用LoaderManager.LoaderCallbacks方法干涉加载进程当指定事件发生。更多的讨论主题,看Using the LoaderManager Callbacks.

 

重新启动加载程序

当你使用initLoader(),像上面展示的,它使用一个已经存在的loader当一个指定的Id。假如不存在,它会创建一个。但是一些你想丢弃的老的数据和重新开始。

 

去掉去你老数据,你使用restartLoader()。比如,SearchView.OnQueryTextListener重器加载器当你使用查询改变时。这个加载器需要重新启动时他可以使用修改过的过滤器。

public boolean onQueryTextChanged(String newText) {
    // Called when the action bar search text has changed.  Update
    // the search filter, and restart the loader to do a new query
    // with this filter.
    mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
    getLoaderManager().restartLoader(0, null, this);
    return true;
}

使用LoaderManager回调

LoaderManager.LoaderCallbacks是一个回调接口让一个客户端和LoaderManager交互。

加载器,在指定CursorLoader,预计保留数据在停止后数据。这个允许应用保持数据在通过activity或fragment的onStop和onStart方法里,所以当用户返回一个应用,他们不会等数据重新加载。你使用LoaderManager.LoaderCallbacks方法当你知道当你出创建一个新的加载器,并且告诉应用当它停止使用。

 

LoaderManager.LoaderCallbacks包括这些方法:

1.      onCreateLoade():实例化并且返回一个新的加载器id。

2.      onLoadFinished():调用当创建的加载器结束加载前。

3.      onLoaderReset():调用当创建的加载器被重置,因此使数据都失效。

 

这些方法描述更多在下面部分。

onCreateLoader

当你想访问一个加载器(比如,通过initLoader()),这个可以检查是否加载器指定ID已经存在。假如不存在,他就会触发LoaderManager.LoaderCallbacks方法onCreateLoader()。这个你可以创建一个新的加载器。典型的比如CursorLoader,但是你实现的你自己的加载器子类。

         举个例子,在onCreateLoader()回调方法创建一个CursorLoader。你必须建立CursorLoader使用构造方法,这个要求完全设置信息执行一个查询。特别的,他需要:

// If non-null, this is the current filter the user has provided.
String mCurFilter;
...
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // This is called when a new Loader needs to be created.  This
    // sample only has one Loader, so we don't care about the ID.
    // First, pick the base URI to use depending on whether we are
    // currently filtering.
    Uri baseUri;
    if (mCurFilter != null) {
        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                  Uri.encode(mCurFilter));
    } else {
        baseUri = Contacts.CONTENT_URI;
    }

    // Now create and return a CursorLoader that will take care of
    // creating a Cursor for the data being displayed.
    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");
}

 

onLoadFinished

这个方法被调用在创建的加载器结束你后,这个方法是有担保优先被调用为了释放那些被加载器加载的数据。这时你应该移除所有旧的数据,但是你不应该使用你释放的数据从它加载他并且需要关注这些。

这个加载器将释放数据一旦知道应用不在使用它。比如,假如数据是一个游标从CursorLoader,你应该自己调用close()。假如游标被放置在一个CursorAdapter,你应该使用swapCursor()方法所以老的Cursor会被关闭。比如

// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
...

public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    // Swap the new cursor in.  (The framework will take care of closing the
    // old cursor once we return.)
    mAdapter.swapCursor(data);
}

 

onLoaderReset

这个方法被调用当一个先前创建的加载器被重置,因此是数据不可用。这个回调让你寻找当数据打算被释放所以你可以移除他的引用。

这里实现调用swapCursor()用一个null:

// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
...

public void onLoaderReset(Loader<Cursor> loader) {
    // This is called when the last Cursor provided to onLoadFinished()
    // above is about to be closed.  We need to make sure we are no
    // longer using it.
    mAdapter.swapCursor(null);
}

例子:

一个例子,这里有实现所有一个Fragment展示一个ListView包含查询结果用内容提供器。他使用一个CursorLoader管理查询在提供者。为一个应用访问用户联系人在例子中展示,在它的清单中需要包含READ_CONTENT权限。

 

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

    // This is the Adapter being used to display the list's data.
    SimpleCursorAdapter mAdapter;

    // If non-null, this is the current filter the user has provided.
    String mCurFilter;

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

        // Give some text to display if there is no data.  In a real
        // application this would come from a resource.
        setEmptyText("No phone numbers");

        // We have a menu item to show in action bar.
        setHasOptionsMenu(true);

        // Create an empty adapter we will use to display the loaded data.
        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);

        // Prepare the loader.  Either re-connect with an existing one,
        // or start a new one.
        getLoaderManager().initLoader(0, null, this);
    }

    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Place an action bar item for searching.
        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) {
        // Called when the action bar search text has changed.  Update
        // the search filter, and restart the loader to do a new query
        // with this filter.
        mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
        getLoaderManager().restartLoader(0, null, this);
        return true;
    }

    @Override public boolean onQueryTextSubmit(String query) {
        // Don't care about this.
        return true;
    }

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

    // These are the Contacts rows that we will retrieve.
    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) {
        // This is called when a new Loader needs to be created.  This
        // sample only has one Loader, so we don't care about the ID.
        // First, pick the base URI to use depending on whether we are
        // currently filtering.
        Uri baseUri;
        if (mCurFilter != null) {
            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                    Uri.encode(mCurFilter));
        } else {
            baseUri = Contacts.CONTENT_URI;
        }

        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.
        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) {
        // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)
        mAdapter.swapCursor(data);
    }

    public void onLoaderReset(Loader<Cursor> loader) {
        // This is called when the last Cursor provided to onLoadFinished()
        // above is about to be closed.  We need to make sure we are no
        // longer using it.
        mAdapter.swapCursor(null);
    }
}

更多的例子:

这里不同的简单在apiDemos列举了怎样使用加载器:

1.      LoaderCursor-一个版本是上面的片段。

2.      LoaderThrottle-一个例子怎么样使用限流来减少查询内容提供者的数量当数据改变时。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linkers and Loaders是指链接器和装载器,是计算机领域中的一种重要工具,主要用于将程序的各个部分合并在一起并最终加载到内存中运行。 链接器的主要工作是将多个目标文件合并成一个可执行文件。目标文件包含机器语言指令和符号表信息,链接器将各个目标文件的符号表信息进行合并,并解决模块之间的引用问题,使得程序能正确地执行。 装载器的主要工作是将可执行文件加载到计算机的内存中运行。装载器将可执行文件中的各个段按照一定的地址空间进行装载,并进行重定位等操作,确保程序能够在内存中正确执行。 总之,链接器和装载器是构建可执行程序需要用到的重要工具,对于程序的可靠性、效率和安全性都具有重要作用。 ### 回答2: linkers and loaders是计算机科学中用于程序编译的工具。Linkers在编译过程中将多个目标文件合并成一个可执行文件,同时也会解决外部和内部符号的引用问题。Loaders则是将可执行文件加载到内存中,并把符号解析成运行时地址,最终使程序在计算机上运行。 linkers在编译过程中实现了模块化编程,将单独编写的多个目标文件链接在一起。linkers将程序中各个部分之间的符号和引用关系整合在一起,实现一个完整的可执行程序。linkers主要有静态链接和动态链接两种形式,静态链接将库文件直接合并到可执行文件中,而动态链接则是在程序运行时动态加载库文件。 loaders则负责将可执行文件从磁盘加载到内存中去。借助加载器,操作系统可以根据可执行文件中文件头和段表信息将程序映射到内存中的相应地址,方便操作系统进行命令的调用和运行。 总之,linkers和loaders是编译过程中非常重要的组成部分。它们不仅使编译工作更加高效和灵活,同时也是计算机开发中程序正确性和性能的关键。 ### 回答3: linker是编译后的程序中用来处理符号链接的工具。它的作用是将不同程序模块(source file, object file)之间的符号联系起来。在链接过程中,linker会分析程序中使用到的符号,并将这些符号与其对应的地址进行关联,以便程序中的不同模块能够相互调用。同时,linker也会将所有的模块组合成一个可执行文件,方便程序的执行。 loader是将程序加载入内存并实现分页与映射的软件。loader的主要作用是将程序文件从磁盘上读入内存,并根据程序的逻辑要求,将其按照合适的方式映射到内存中的合适位置。同时,loader还负责分配与管理程序所需要的内存空间,维护程序在内存中的状态,以及实现程序的执行。 在计算机科学领域中,linkers和loaders是非常重要的工具。它们帮助编程人员将不同的程序模块链接起来,并在不同的系统中进行适当的加载。对于任何一个开发者而言,了解和掌握linkers和loaders都是非常重要的基本技能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值