Android AsyncTaskLoader基本示例。(安卓)
我在我的应用程序中使用了一个加载器,根据我使用这个加载器对联系人执行的查询结果,我执行一些计算并将它们存储回Sqlite数据库。我希望这个操作是异步的,但是我混淆了使用异步任务,因为我有很多不同的数据类型要返回,或者我应该使用简单的处理程序或AsyncTaskLoader,我希望它是简单的,因为我是新的加载程序。我试图搜索AsyncTaskLoader的示例,但在我的场景中,火箭科学(rocket science)似乎是这三个示例中任何一个的基础和简单功能示例都会非常有用 由于蜂巢和v4兼容库,因此可以使用Android AsyncTaskLoader基本示例。(安卓),android,android-asynctask,android-handler,Android,Android Asynctask,Android Handler,我在我的应用程序中使用了一个加载器,根据我使用这个加载器对联系人执行的查询结果,我执行一些计算并将它们存储回Sqlite数据库。我希望这个操作是异步的,但是我混淆了使用异步任务,因为我有很多不同的数据类型要返回,或者我应该使用简单的处理程序或AsyncTaskLoader,我希望它是简单的,因为我是新的加载程序。我试图搜索AsyncTaskLoader的示例,但在我的场景中,火箭科学(rocket science)似乎是这三个示例中任何一个的基础和简单功能示例都会非常有用 由于蜂巢和v4兼容库,
AsyncTaskLoader
。据我所知,AsyncTaskLoader
可以通过屏幕翻转等配置更改生存下来。但是使用AsyncTask
可能会搞乱配置更改
关键信息:AsyncTaskLoader
是Loader
的子类。该类执行与AsyncTask相同的功能,但更好一些,它在处理配置更改(屏幕方向)时也很有用
这里给出了一个很好的例子和解释。
谷歌在API文档中有一个很好的例子。
Android设计模式提供了一些更详细的细节和加载程序背后的推理
本教程肯定会对您有所帮助 如果您希望使用AsyncTaskLoader,这是一个很好的示例 编辑:我决定制作一个更简单的解决方案(基于):
公共抽象类AsyncTaskLoaderEx扩展了AsyncTaskLoader{
私有静态最终AtomicInteger sCurrentUniqueId=新的AtomicInteger(0);
私有T-mData;
公共布尔值hasResult=false;
公共静态int getNewUniqueLoaderId(){
返回sCurrentUniqueId.getAndIncrement();
}
公共AsyncTaskLoaderEx(最终上下文){
超级(上下文);
onContentChanged();
}
@凌驾
开始加载时受保护的void(){
if(takeContentChanged())
力载荷();
//该零件应从支架库27.1.0中移除:
//否则如果(hasResult)
//交付结果(mData);
}
@凌驾
公共无效交付结果(最终T数据){
mData=数据;
hasResult=true;
super.deliverResult(数据);
}
@凌驾
受保护的void onReset(){
super.onReset();
onStopLoading();
如果(结果){
onReleaseResources(mData);
mData=null;
hasResult=false;
}
}
受保护的无效onReleaseResources(T数据){
//无事可做。
}
公共T getResult(){
返回mData;
}
}
用法:
在您的活动中:
getSupportLoaderManager().initLoader(TASK_ID, TASK_BUNDLE, new LoaderManager.LoaderCallbacks<Bitmap>() {
@Override
public Loader<Bitmap> onCreateLoader(final int id, final Bundle args) {
return new ImageLoadingTask(MainActivity.this);
}
@Override
public void onLoadFinished(final Loader<Bitmap> loader, final Bitmap result) {
if (result == null)
return;
//TODO use result
}
@Override
public void onLoaderReset(final Loader<Bitmap> loader) {
}
});
getSupportLoaderManager().initLoader(任务ID,任务包,新的LoaderManager.LoaderCallbacks(){
@凌驾
公共加载器onCreateLoader(最终int-id,最终Bundle-args){
返回新的ImageLoadingTask(MainActivity.this);
}
@凌驾
public void onLoadFinished(最终加载程序,最终位图结果){
如果(结果==null)
返回;
//待办事项使用结果
}
@凌驾
公共无效onLoaderReset(最终加载程序){
}
});
内部静态类或普通类:
private static class ImageLoadingTask extends AsyncTaskLoaderEx<Bitmap> {
public ImageLoadingTask (Context context) {
super(context);
}
@Override
public Bitmap loadInBackground() {
//TODO load and return bitmap
}
}
私有静态类ImageLoadingTask扩展了AsyncTaskLoaderEx{
公共ImageLoadingTask(上下文){
超级(上下文);
}
@凌驾
公共位图加载背景(){
//TODO加载并返回位图
}
}
更新:从支持库27.1.0开始,情况发生了一些变化(链接): 在版本27.1.0中,每次激活活动时都会调用onStartLoading() 开始了。由于在onStartLoading()中调用deliverResult(),因此 触发器onLoadFinished()。这是工作的预期 您应该从onStartLoading()中删除对deliverResult()的调用 因为它不是必需的(装载机已经在 loadInBackground(),无需您进行任何额外工作) 我已经为这一更改更新了上面的代码
编辑:
更新后的kotlin版本可以找到。我喜欢这个简单的例子
我更喜欢用Android。这很容易
Task.callInBackground(新的Callable(){
公开作废通知(){
//做一大堆事情。
}
}).继续使用(…);
下面是实现AsyncTaskLoader
的分步教程。或者在
LoaderManager.LoaderCallbacks
,并创建一个static int
,以唯一标识加载程序,并创建一个字符串键将字符串url传递给加载程序
public class MainActivity extends AppCompatActivity
implements LoaderManager.LoaderCallbacks<String>{
public static final int OPERATION_SEARCH_LOADER = 22;
public static final String OPERATION_QUERY_URL_EXTRA = "query";
//...}
onCreateLoader()
返回一个新的AsyncTaskLoader
作为匿名内部类,其中this
作为构造函数的参数,并在匿名内部重写loadInBackground
和onStartLoading
内部阶级
@Override
public Loader<String> onCreateLoader(int id, final Bundle args) {
return new AsyncTaskLoader<String>(this) {
@Override
public String loadInBackground() {
//Think of this as AsyncTask doInBackground() method, here you will actually initiate Network call
return null;
}
@Override
protected void onStartLoading() {
//Think of this as AsyncTask onPreExecute() method,start your progress bar,and at the end call forceLoad();
forceLoad();
}
};
}
onCreate
内部,使用操作\u SEARCH\u loader作为ID初始化加载程序,bundle为null,上下文为null
getSupportLoaderManager().initLoader(OPERATION_SEARCH_LOADER, null, this);
private void makeOperationSearchQuery(String url) {
// Create a bundle called queryBundle
Bundle queryBundle = new Bundle();
// Use putString with OPERATION_QUERY_URL_EXTRA as the key and the String value of the URL as the value
queryBundle.putString(OPERATION_QUERY_URL_EXTRA,url);
// Call getSupportLoaderManager and store it in a LoaderManager variable
LoaderManager loaderManager = getSupportLoaderManager();
// Get our Loader by calling getLoader and passing the ID we specified
Loader<String> loader = loaderManager.getLoader(OPERATION_SEARCH_LOADER);
// If the Loader was null, initialize it. Else, restart it.
if(loader==null){
loaderManager.initLoader(OPERATION_SEARCH_LOADER, queryBundle, this);
}else{
loaderManager.restartLoader(OPERATION_SEARCH_LOADER, queryBundle, this);
}
}
private void makeOperationSearchQuery(字符串url){
//创建一个名为queryBundle的包
Bundle queryBundle=新Bundle();
//使用putString,操作\u QUERY\u URL\u EXTRA作为键,URL的字符串值作为值
putString(操作\u查询\u URL\u额外,URL);
//调用getSupportLoaderManager并将其存储在LoaderManager变量中
LoaderManager LoaderManager=getSupportLoaderManager();
//通过调用getLoader并传递我们指定的ID来获取我们的Loader
@Override
public Loader<String> onCreateLoader(int id, final Bundle args) {
//Here we will initiate AsyncTaskLoader
return null;
}
@Override
public void onLoadFinished(Loader<String> loader, String operationResult) {
//Think of this as AsyncTask onPostExecute method, the result from onCreateLoader will be available in operationResult variable and here you can update UI with the data fetched.
Log.d("MAINACTIVITY","result : "+ operationResult);
}
@Override
public void onLoaderReset(Loader<String> loader) {
//Don't bother about it, Android Studio will override it for you
}
@Override
public Loader<String> onCreateLoader(int id, final Bundle args) {
return new AsyncTaskLoader<String>(this) {
@Override
public String loadInBackground() {
//Think of this as AsyncTask doInBackground() method, here you will actually initiate Network call
return null;
}
@Override
protected void onStartLoading() {
//Think of this as AsyncTask onPreExecute() method,start your progress bar,and at the end call forceLoad();
forceLoad();
}
};
}
@Override
public String loadInBackground() {
String url = args.getString(OPERATION_QUERY_URL_EXTRA);//This is a url in string form
if (url!=null&&"".equals(url)) {
return null;//if url is null, return
}
String operationResult="";
try {
operationResult = NetworkUtils.getResponseFromHttpUrl(url);//This just create a HTTPUrlConnection and return result in strings
} catch (IOException e) {
e.printStackTrace();
}
return operationResult;
}
getSupportLoaderManager().initLoader(OPERATION_SEARCH_LOADER, null, this);
private void makeOperationSearchQuery(String url) {
// Create a bundle called queryBundle
Bundle queryBundle = new Bundle();
// Use putString with OPERATION_QUERY_URL_EXTRA as the key and the String value of the URL as the value
queryBundle.putString(OPERATION_QUERY_URL_EXTRA,url);
// Call getSupportLoaderManager and store it in a LoaderManager variable
LoaderManager loaderManager = getSupportLoaderManager();
// Get our Loader by calling getLoader and passing the ID we specified
Loader<String> loader = loaderManager.getLoader(OPERATION_SEARCH_LOADER);
// If the Loader was null, initialize it. Else, restart it.
if(loader==null){
loaderManager.initLoader(OPERATION_SEARCH_LOADER, queryBundle, this);
}else{
loaderManager.restartLoader(OPERATION_SEARCH_LOADER, queryBundle, this);
}
}
private void loadContent() {
getLoaderManager().initLoader(1000, new Bundle(),
new LoaderManager.LoaderCallbacks<List<String>>() {
@Override
public Loader<List<String>> onCreateLoader(int id, Bundle args) {
return new AsyncTaskLoader<List<String>>(MainActivity.this.getApplicationContext()) {
@Override
public List<String> loadInBackground() {
Log.i("B", "Load background data ");
ArrayList<String> data = new ArrayList<>();
for (int i = 0; i < 5000; i++) {
data.add("Data." + i + " " + System.currentTimeMillis());
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return data;
}
};
}
@Override
public void onLoadFinished(Loader<List<String>> loader, List<String> data) {
Log.i("B", "Here are your data loaded" + data);
if (!loader.isAbandoned()) {
mAdapter.setData(data); // Read also about RecyclerView
}
}
@Override
public void onLoaderReset(Loader<List<String>> loader) {
Log.i("B", "Loader reset");
}
}).forceLoad();
}
@Override
protected void onDestroy() {
// Abandon the loader so that it should not attempt to modify already dead GUI component
getLoaderManager().getLoader(1000).abandon();
super.onDestroy();
}