2011-10-11 419 views
1

时不时用户例外得到以下(我自己不能复制):java.lang.IllegalStateException - 为什么? (安卓,ListAdapter)

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(2131165209, class android.widget.ListView) with Adapter(class com.tfd.mobile.TfdSearch.TfdSearch$SearchList$PagesListAdapter)] 
at android.widget.ListView.layoutChildren(ListView.java:1567) 
at android.widget.AbsListView.onTouchModeChanged(AbsListView.java:2093) 
at android.view.ViewTreeObserver.dispatchOnTouchModeChanged(ViewTreeObserver..java:591) 
at android.view.ViewRoot.ensureTouchModeLocally(ViewRoot.java:2023) 
at android.view.ViewRoot.ensureTouchMode(ViewRoot.java:2007) 
at android.view.ViewRoot.handleMessage(ViewRoot.java:1775) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:123) 
at android.app.ActivityThread.main(ActivityThread.java:4633) 
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:858) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
at dalvik.system.NativeStart.main(Native Method) 

我找不到为什么会发生。我使用线程,但主线程中的所有底层数据更改。我总是调用_adapter.notifyDataSetChanged();数据更改后。请帮帮我!这是我的代码:

private class SearchList extends LinkedList<PageInfo> 
{ 
    private static final long serialVersionUID = 1L; 

    private PagesListAdapter _adapter; 

    public PagesListAdapter getAdapter() 
    { 
     return _adapter; 
    } 

    public SearchList(ListView listView) 
    { 
     super(); 
     _adapter = new PagesListAdapter(activity, this); 
     listView.setAdapter(_adapter); 
    } 

    private void getSuggestions(final String typedText) 
    { 
     showProgressVisibility(true); 
     new Thread(new Runnable() { 

      public void run() { 
       android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND); 
       final String[] sugg = TfdMode.getMode().getSuggestions(typedText); 

       activity.runOnUiThread(new Runnable() { 
        public void run() { 
         if (sugg != null) 
         { 
          clear(); 
          for (String s: sugg) { 
           add(new PageInfo(s, PageInfo.PAGE_SUGGESTION, null)); 
          } 
         } 
         _adapter.notifyDataSetChanged(); 
         showProgressVisibility(false); 
        } 
       }); 
      } 
     }).start(); 
    } 

    public void refresh(final String typedText) 
    { 
     if (typedText.length() >= 3) 
     { 
      // use suggestions (separate thread) 
      getSuggestions(typedText); 
     } 
     else 
     { 
      // use recent 
      clear(); 
      for (PageInfo p: TfdMode.getMode().recentManager.pages) { 
       if (p.text.startsWith(typedText)) add(p); 
      } 

      if (size() == 0 && typedText.length() > 0) 
       getSuggestions(typedText); // if no recent - use suggestions 
      else 
       _adapter.notifyDataSetChanged(); 
     } 

    } 


    public class PagesListAdapter extends ArrayAdapter<PageInfo> { 

     private LayoutInflater mInflater; 

     public PagesListAdapter(Context context, List<PageInfo> objects) { 
      super(context, R.layout.bookmarks_item, R.id.bookmark_title, objects); 
      mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 

      final PageInfo b = getItem(position); 
      View row = convertView == null ? mInflater.inflate(R.layout.bookmarks_item, null) : convertView; 

      TextView title = (TextView) row.findViewById(R.id.bookmark_title); 
      ImageView img = (ImageView) row.findViewById(R.id.bookmark_img); 
      ImageView del = (ImageView) row.findViewById(R.id.bookmark_img_del); 
      del.setVisibility(View.GONE); 

      title.setText(b.text); 
      int iconId = b.getIconResId(); 

      if (iconId != -1) 
      { 
       img.setImageResource(iconId); 
       img.setVisibility(View.VISIBLE); 
      } 
      else 
       img.setVisibility(View.INVISIBLE); 


      return row; 
     } 
    } 


}; 

数据更改的唯一地方 - “刷新”方法调用时。它总是从主线程调用。为什么它仍然发生?帮帮我!

什么时候发生java.lang.IllegalStateException EXCEPTION? ** ** 当我明确从非UI线程中执行“刷新”的方法,我在_adapter.notifyDataSetChanged的时刻得到另一个异常(CalledFromWrongThreadException)()调用:

10-12 13:20:29.057: ERROR/AndroidRuntime(24746): FATAL EXCEPTION: Thread-27 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at android.view.ViewRoot.checkThread(ViewRoot.java:2837) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at android.view.ViewRoot.invalidateChild(ViewRoot.java:619) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:645) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at android.view.ViewGroup.invalidateChild(ViewGroup.java:2505) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at android.view.View.invalidate(View.java:5192) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at android.view.View.setFlags(View.java:4569) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at android.view.View.setVisibility(View.java:3083) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at com.tfd.mobile.TfdSearch.TfdSearch.showProgressVisibility(TfdSearch.java:315) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at com.tfd.mobile.TfdSearch.TfdSearch.access$0(TfdSearch.java:313) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at com.tfd.mobile.TfdSearch.TfdSearch$SearchList.getSuggestions(TfdSearch.java:783) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at com.tfd.mobile.TfdSearch.TfdSearch$SearchList.refresh(TfdSearch.java:823) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at com.tfd.mobile.TfdSearch.TfdSearch$8$1.run(TfdSearch.java:443) 
10-12 13:20:29.057: ERROR/AndroidRuntime(24746):  at java.lang.Thread.run(Thread.java:1096) 
+0

你在哪里调用刷新? – Cristian

+0

我打电话刷新: 1. editText的TextChangeListener。 2. setDisplayMode方法。此方法从代码周围的不同位置调用,但在调用刷新之前很多UI对象都会触及此方法,因此如果从非UI线程调用它,在“刷新”获得调用机会之前它会失败更多。 –

回答

1

_adapter.notifyDataSetChanged();

这必须在UI线程上执行。使用处理程序或runOnUiThread