【问题标题】:java.lang.IllegalStateException: The content of the adapter has changed but ListView.... inspite of calling notifydatasetchanged()java.lang.IllegalStateException:适配器的内容已更改,但 ListView.... 尽管调用了 notifydatasetchanged()
【发布时间】:2012-10-19 16:38:54
【问题描述】:

通过后台线程(异步任务)更新 listactivty 内容的最佳实践是什么?

1) 只要我操作适配器的内容,我就会调用 notifyDataSetChanged() 来更新适配器,但是当用户滚动或单击列表时,我的应用程序仍然会关闭。任何防止这种情况的指示都会非常有帮助。

Logcat: java.lang.IllegalStateException:适配器的内容发生了变化,但ListView没有收到通知。

2) 我应该在哪里更新 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)

【问题讨论】:

  • listView.postInvalidate() 怎么样?
  • 请张贴日志猫以便更好地了解其余内容

标签: android android-asynctask listactivity


【解决方案1】:

2) 我应该在哪里更新 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) {

       }
      }

【讨论】:

    【解决方案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 导致您的应用程序崩溃。

    【讨论】:

    • 我也是这么想的。但是我的 listactivty 没有 on itemclick 侦听器。此外,有时我会收到以下错误 java.lang.IndexOutOfBoundsException: Invalid index 2, size is 0. 我怀疑崩溃发生在滚动:-(
    【解决方案3】:

    此异常具有误导性 - 原因有很多。 此崩溃的一个原因是 ArrayList 对象无法完全更改。 所以,当我删除一个项目时,我必须这样做:

    mList.clear();
    mList.addAll(newDataList);
    

    这为我解决了崩溃问题。

    【讨论】:

      【解决方案4】:

      这个问题困扰了我很长时间。

      当我在调用Adapter.notifyDataSetChanged() 之前使用MotionEvent 单击listView 时,确实会导致非法状态异常

      所以我认为在更新listView 之前调用ListView.setEnable(false) 很有用。

      【讨论】:

        猜你喜欢
        • 2015-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多