博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android应用程序后台加载数据
阅读量:4647 次
发布时间:2019-06-09

本文共 5060 字,大约阅读时间需要 16 分钟。

从ContentProvider查询你需要显示的数据是比较耗时的。如果你在Activity中直接执行查询的操作,那么有可能导致Activity出现ANR的错误。即使没有发生ANR,用户也容易感知到一个令人烦恼的UI卡顿。为了避免那些问题,你应该在另外一个线程中执行查询的操作,等待查询操作完成,然后再显示查询结果。

通过CursorLoader对象,你可以用一种简单的方式实现异步查询,查询结束时它会和Activity进行重新连接。 CursorLoader不仅仅能够实现在后台查询数据,还能够在查询数据发生变化时自动执行重新查询的操作。

主题一:使用CursorLoader执行查询任务

CursorLoader通过ContentProvider在后台执行一个异步的查询操作,并且返回数据给调用它的Activity或者FragmentActivity。这使得Activity或者FragmentActivity能够在查询任务正在执行的同时继续与用户进行其他的交互操作。

如何定义使用CursorLoader的Activity?

为了在Activity或者FragmentActivity中使用CursorLoader,它们需要实现LoaderCallbacks<Cursor>接口。CursorLoader会调用LoaderCallbacks<Cursor>定义的这些回调方法与Activity进行交互。

public class PhotoThumbnailFragment extends FragmentActivity implements        LoaderManager.LoaderCallbacks
{...}

如何初始化查询?

为了初始化查询,需要调用LoaderManager.initLoader()。这个方法可以初始化LoaderManager的后台查询框架。你可以在用户输入查询条件之后触发初始化的操作,如果你不需要用户输入数据作为查询条件,你可以在onCreate()或者onCreateView()里面触发这个方法。

// Identifies a particular Loader being used in this component    private static final int URL_LOADER = 0;    ...    /* When the system is ready for the Fragment to appear, this displays     * the Fragment's View     */    public View onCreateView(            LayoutInflater inflater,            ViewGroup viewGroup,            Bundle bundle) {        ...        /*         * Initializes the CursorLoader. The URL_LOADER value is eventually passed         * to onCreateLoader().         */        getLoaderManager().initLoader(URL_LOADER, null, this);        ...    }

需要注意的是:getLoaderManager()仅存在于Fragment类中;如果想要在FragmentActivity中获取到LoaderManager实例,可以调用getSupportLoaderManager()。

如何启动查询任务?

一旦后台任务被初始化好,它会执行你实现的回调方法onCreateLoader()。为了启动查询任务,会在这个方法里面返回CursorLoader。你可以初始化一个空的CursorLoader然后使用它的方法来定义你的查询条件,或者你可以在初始化CursorLoader对象的时候就同时定义好查询条件。

/** Callback that's invoked when the system has initialized the Loader and* is ready to start the query. This usually happens when initLoader() is* called. The loaderID argument contains the ID value passed to the* initLoader() call.*/@Overridepublic Loader
onCreateLoader(int loaderID, Bundle bundle){ /* * Takes action based on the ID of the Loader that's being created */ switch (loaderID) { case URL_LOADER: // Returns a new CursorLoader return new CursorLoader( getActivity(), // Parent activity context mDataUrl, // Table to query mProjection, // Projection to return null, // No selection clause null, // No selection arguments null // Default sort order ); default: // An invalid id was passed in return null; }}

一旦后台查询任务获取到了这个Loader对象,就开始在后台执行查询的任务。当查询完成之后,会执行onLoadFinished()这个回调函数。

主题二:处理查询的结果

在 onCreateLoader()的回调里面使用CursorLoader执行加载数据的操作。Loader查询完后会调用Activity或者FragmentActivity的LoaderCallbacks.onLoadFinished()将结果回调回来。这个回调方法的参数之一是Cursor,它包含了查询的数据。你可以使用Cursor对象来更新需要显示的数据或者进行下一步的处理。

除了onCreateLoader()与onLoadFinished(),你也需要实现onLoaderReset()。这个方法在CursorLoader检测到Cursor上的数据发生变化的时候会被触发。当数据发生变化时,系统也会触发重新查询的操作。

如何处理查询的结果?

为了显示CursorLoader返回的Cursor数据,需要使用实现AdapterView的视图组件,,并为这个组件绑定一个实现了CursorAdapter的Adapter。系统会自动把Cursor中的数据显示到View上。

你可以在显示数据之前建立View与Adapter的关联。然后在onLoadFinished()的时候把Cursor与Adapter进行绑定。一旦你把Cursor与Adapter进行绑定之后,系统会自动更新View。当Cursor上的内容发生改变的时候,也会触发这些操作。

public String[] mFromColumns = {    DataProviderContract.IMAGE_PICTURENAME_COLUMN};public int[] mToFields = {    R.id.PictureName};// Gets a handle to a List ViewListView mListView = (ListView) findViewById(R.id.dataList);/* * Defines a SimpleCursorAdapter for the ListView * */SimpleCursorAdapter mAdapter =    new SimpleCursorAdapter(            this,                // Current context            R.layout.list_item,  // Layout for a single row            null,                // No Cursor yet            mFromColumns,        // Cursor columns to use            mToFields,           // Layout fields to use            0                    // No flags    );// Sets the adapter for the viewmListView.setAdapter(mAdapter);.../* * Defines the callback that CursorLoader calls * when it's finished its query */@Overridepublic void onLoadFinished(Loader
loader, Cursor cursor) { ... /* * Moves the query results into the adapter, causing the * ListView fronting this adapter to re-display */ mAdapter.changeCursor(cursor);}

如何处理废旧的Cursor引用?

当Cursor失效的时候,CursorLoader会被重置。这通常发生在Cursor相关的数据改变的时候。在重新执行查询操作之前,系统会执行你的onLoaderReset()回调方法。在这个回调方法中,你应该删除当前Cursor上的所有数据,避免发生内存泄露。一旦onLoaderReset()执行结束,CursorLoader就会重新执行查询操作。

/* * Invoked when the CursorLoader is being reset. For example, this is * called if the data in the provider changes and the Cursor becomes stale. */@Overridepublic void onLoaderReset(Loader
loader) { /* * Clears out the adapter's reference to the Cursor. * This prevents memory leaks. */ mAdapter.changeCursor(null);}

转载于:https://www.cnblogs.com/CVstyle/p/6391855.html

你可能感兴趣的文章
测试用例方法总结
查看>>
基数---SQL Server 2008 Bible
查看>>
第一个JSP程序
查看>>
数组常用的API——splice()截取
查看>>
sbt教程
查看>>
djang1.7 复制粘贴小项目(generic View的使用)
查看>>
Python For Delphi---更好地协同(续)
查看>>
Java的内存泄漏
查看>>
152-PHP htmlspecialchars函数
查看>>
061-PHP函数定义默认参数
查看>>
Genymotion下载模拟器失败解决方案
查看>>
The Apostrophe and the Quote Function ‘和引用函数 未翻译完)
查看>>
kv.go
查看>>
利用截取字符串,生成已声明的字符串中的4位随机验证码。
查看>>
Spring 事务模型
查看>>
【MM系列】SAP S/4 HANA BP创建客户/供应商的一点想法
查看>>
【HANA系列】SAP HANA XS使用JavaScript数据交互详解
查看>>
【HANA系列】SAP HANA SQL获取上周的周一
查看>>
对称矩阵
查看>>
轮播图笔记!
查看>>