在使用AsyncTaskLoader的时候,遇到两个问题:
1.继承AsyncTaskLoader并实现了必要的方法后,发现loadInBackground()没有被执行
  在网上查找之后,得到如下解决方法:

继承AsyncTaskLoader后,需要重载以下方法供系统调用:

@Overrideprotected void onStartLoading() {// TODO Auto-generated method stubsuper.onStartLoading();forceLoad();}

2.使用问题1的解决方案后,Loader开始工作了,但是又遇到了新的问题,我在Activity里面写了一个ListView,ListView的数据通过AsyncTaskLoader
  来进行加载,当从当前Activity跳到另一个Activity并按back键返回时,此时没有问题,但是当点击ListView中的某一项时,报出以下的错误:
  E/AndroidRuntime(1141): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(16908298, class android.widget.ListView) with Adapter(class com.study.ActivityAdapter)]
以下是我自定义AsyncTaskLoader的代码:

public class ActivityListLoader extends AsyncTaskLoader{private Context context;private Bundle args;private String path;private List> data;public ActivityListLoader(Context context,Bundle args) {super(context);this.context = context;this.args = args;path = args.getString("path");data = new ArrayList>();}@Overridepublic Integer loadInBackground() {PackageManager pm = context.getPackageManager();Intent matchIntent = new Intent();matchIntent.setAction(Constants.ACTION_MAIN);matchIntent.addCategory(Constants.CATEGORY_STUDY);matchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);List list = pm.queryIntentActivities(matchIntent,0);String label = null;for(ResolveInfo info:list){label = info.loadLabel(pm).toString();if(label.startsWith(path)){String[] paths = path.split("/");String[] files = label.split("/");Map map = new HashMap();Intent intent = new Intent();intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);int pathlen = paths.length;if(path.equals("")){pathlen = 0;}if(files.length - pathlen == 1){map.put("isFile", true);intent.setComponent(new ComponentName(info.activityInfo.packageName, info.activityInfo.name));map.put("intent", intent);}else{map.put("isFile", false);intent.setClass(context, MainActivity.class);intent.putExtra("path", path+files[pathlen]+"/");map.put("intent", intent);}data.add(map);}}return 0;}@Overrideprotected void onStartLoading() {// TODO Auto-generated method stubsuper.onStartLoading();forceLoad();}public List> getData(){return data;}}MainActivity的代码:public class MainActivity extends ListActivity implementsLoaderCallbacks {private ListActivity context;private List> datalist;enum Type {ShowProgress, DismissProgress,UpdateAdapter};private ProgressDialog progress;private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {Type type = (Type) msg.obj;switch (type) {case ShowProgress:progress.show();break;case DismissProgress:if(progress.isShowing())progress.dismiss();break;case UpdateAdapter:ActivityAdapter adapter = new ActivityAdapter(context, datalist);setListAdapter(adapter);adapter.notifyDataSetChanged();break;default:break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);context = this;initProgressDialog();Intent intent = getIntent();String path = intent.getStringExtra("path");if (path == null)path = "";Bundle args = new Bundle();args.putString("path", path);getLoaderManager().initLoader(0, args, this);Message msg = Message.obtain(handler, 0, Type.ShowProgress);msg.sendToTarget();setListAdapter(new ActivityAdapter(this, new ArrayList>()));getListView().setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {@SuppressWarnings("unchecked")Map map = (Map) getListAdapter().getItem(position);Intent intent = (Intent)map.get("intent");startActivity(intent);}});}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}private void initProgressDialog(){progress = new ProgressDialog(this);progress.setMessage("加载所有的Activity信息");progress.setCanceledOnTouchOutside(false);}@Overridepublic Loader onCreateLoader(int id, Bundle args) {return new ActivityListLoader(context, args);}@Overridepublic void onLoadFinished(Loader loader, Integer data) {ActivityListLoader aloader = (ActivityListLoader) loader;datalist = aloader.getData();LogUtils.e("debug");Message msg = Message.obtain(handler, 0, Type.DismissProgress);msg.sendToTarget();Message msgUpdate = Message.obtain(handler, 0, Type.UpdateAdapter);msgUpdate.sendToTarget();}@Overridepublic void onLoaderReset(Loader loader) {LogUtils.e("debug");Message msgUpdate = Message.obtain(handler, 0, Type.UpdateAdapter);msgUpdate.sendToTarget();}}

更新ListView数据的操作都是发生在UI线程,所以应该是系统在我们不知道的地方更新了数据而没有通知ListView.
查看Activity.java的源码可以看到:

protected void onStart() {if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this);mCalled = true;if (!mLoadersStarted) {mLoadersStarted = true;if (mLoaderManager != null) {mLoaderManager.doStart(); //系统会执行Loader的onStartLoading函数} else if (!mCheckedForLoaderManager) {mLoaderManager = getLoaderManager(null, mLoadersStarted, false);}mCheckedForLoaderManager = true;}getApplication().dispatchActivityStarted(this);}

Activity恢复的时候,会重新调用onStart函数,从而最终调用到我们Loader里的onStartLoading函数,
而我们的onStartLoading函数是这样:

@Overrideprotected void onStartLoading() {// TODO Auto-generated method stubsuper.onStartLoading();forceLoad();}

也就是说,不管如何,都会在后台将数据重新加载一遍,因为是系统调用的,所以没有通知ListView,造成数据的不同步.
到这里,解决方案就呼之欲出了:
改造如下:

@Overrideprotected void onStartLoading() {// TODO Auto-generated method stubsuper.onStartLoading();if(data.size() == 0)forceLoad();}

更多相关文章

  1. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  2. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  3. Nginx系列教程(六)| 手把手教你搭建 LNMP 架构并部署天空网络电影
  4. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  5. Pixel修改kernel内核调试
  6. android关于获取摄像头帧数据转成图片
  7. Android7.1修改系统默认多媒体音量大小
  8. Android数据存储(3)SQLite简介和简单的登录与注册源代码
  9. android 第一行代码(第二版)Litepal遇到的问题

随机推荐

  1. kotlin入门系列二---基本语法
  2. 手动修改android模拟器system.img
  3. android EventBus 3.0 官方的混淆配置
  4. RTL8723BU wifi 及 热点移植和测试
  5. 安卓-开发常见问题之android:onClick未定
  6. android级联下拉菜单
  7. android 点击空白处收起键盘和自定义Edit
  8. Android权限机制
  9. android studio 主线程中访问网络,遇到and
  10. Android Build获得系统信息