后台线程(异步任务)更新listactivty的内容需要遵循哪些最佳做法?
1)我操作适配器的内容后立即调用 notifyDataSetChanged()更新适配器,但在用户滚动或单击列表时我的应用程序强制关闭。任何防止这种情况的指针都非常有用。
logcat的: java.lang.IllegalStateException:适配器的内容已更改,但ListView未收到通知。
2)如果exaclty我应该更新listactivity的内容?在doInBackground()或onProgressUpdate()?
中3)当用户点击列表项时,我遇到了常规崩溃。那么在后台操作期间禁用listactivty上的点击事件会解决问题吗?如果是这样,我不确定如何动态删除或设置项目单击侦听器到listactivity。请指教我。
4)我不认为在后台阻止所有ui交互异步任务执行是解决问题的唯一方法。我知道有一种简单的方法可以做到这一点但需要一些帮助。
提前致谢。
这是我的onCreate ......
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fa);
tvStatus=(TextView) findViewById(R.id.tvStatus);
adapter = new SimpleAdapter(
this,
mostPopularList,
R.layout.list_item,
new String[] {"title","author","views","date"},
new int[] {R.id.textView1,R.id.textView2,R.id.textView4,R.id.textView3});
//populateList();
setListAdapter(adapter);
}
我的异步任务......
private class LongOperation extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
// code for adding new listactivty items
}
@Override
protected void onPostExecute(String networkStatus) {
adapter.notifyDataSetChanged();
}
@Override
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(Void... values) {
}
}
Logcat:
我很少也是非法状态的例外......无法重现它。如果我再遇到它会发布logcat。
FATAL EXCEPTION: main
java.lang.IndexOutOfBoundsException: Invalid index 7, size is 4
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257)
at java.util.ArrayList.get(ArrayList.java:311)
at android.widget.SimpleAdapter.bindView(SimpleAdapter.java:147)
at android.widget.SimpleAdapter.createViewFromResource(SimpleAdapter.java:126)
at android.widget.SimpleAdapter.getView(SimpleAdapter.java:114)
at android.widget.AbsListView.obtainView(AbsListView.java:1294)
at android.widget.ListView.makeAndAddView(ListView.java:1727)
at android.widget.ListView.fillDown(ListView.java:652)
at android.widget.ListView.fillGap(ListView.java:623)
at android.widget.AbsListView.trackMotionScroll(AbsListView.java:2944)
at android.widget.AbsListView.onTouchEvent(AbsListView.java:2065)
at android.widget.ListView.onTouchEvent(ListView.java:3315)
at android.view.View.dispatchTouchEvent(View.java:3766)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:897)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1671)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107)
at android.app.Activity.dispatchTouchEvent(Activity.java:2086)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1655)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1671)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107)
at android.app.Activity.dispatchTouchEvent(Activity.java:2086)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1655)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1785)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
答案 0 :(得分:4)
2)如果exaclty我应该更新listactivity的内容?在doInBackground()或onProgressUpdate()?
中
在onProgressUpdate()
内或onPostExecute()内部,因为更改doInBackground()
中的内容并调用异步任务调用可能需要一些时间
@Override
protected void onPostExecute(String networkStatus) {
adapter.notifyDataSetChanged();
}
3)当用户点击列表项时,我遇到了常规崩溃。那么在后台操作期间禁用listactivty上的点击事件会解决问题吗?如果是这样,我不确定如何动态删除或设置项目单击侦听器到listactivity。请指教我。
这不是解决方案。您只需要在UI线程上更新数据集。 (不加载内容,只需从旧版更新为新版)。例如
private class LongOperation extends AsyncTask<String, Void, String> {
@Override
protected List<String> doInBackground(String... params) {
List<String> items = loadUpdatedDataset(params);
return items;
}
@Override
protected void onPostExecute(List<String> loadedItems) {
updateAdapterDataset(loadedItems);
adapter.notifyDataSetChanged();
}
@Override
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(Void... values) {
}
}
答案 1 :(得分:2)
请在本课程中查看。使用AsyncTask和Listview有一个很好的例子 http://android.okhelp.cz/java_android_code.php?o=%5Candroid-15%5CGestureBuilder%5Csrc%5Ccom%5Candroid%5Cgesture%5Cbuilder%5CGestureBuilderActivity.java#Problem
我认为代码中的问题是因为适配器正在更新ListView,此时用户单击ListView导致应用程序崩溃。
答案 2 :(得分:1)
这种例外具有误导性 - 原因很多。 导致此崩溃的一个原因是ArrayList对象无法完全更改。 所以,当我删除一个项目时,我必须这样做:
mList.clear();
mList.addAll(newDataList);
这解决了我的崩溃。
答案 3 :(得分:0)
这个问题让我很烦恼。
当我在调用MotionEvent
之前使用listView
点击Adapter.notifyDataSetChanged()
时,会导致 Illegalstate异常。
所以我认为在更新ListView.setEnable
之前调用listView
(false)很有用。