2013-03-21 32 views
1

我正在使用列表視圖來呈現類似於活動的GridView。有一個OutOfBoundsException。這裏是日誌。在列表視圖OutOfBoundsException

03-21 11:47:13.106: E/AndroidRuntime(597): FATAL EXCEPTION: main 
03-21 11:47:13.106: E/AndroidRuntime(597): java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1 
03-21 11:47:13.106: E/AndroidRuntime(597): at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251) 
03-21 11:47:13.106: E/AndroidRuntime(597): at java.util.ArrayList.get(ArrayList.java:304) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.HeaderViewListAdapter.getView(HeaderViewListAdapter.java:225) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.AbsListView.obtainView(AbsListView.java:2022) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.ListView.measureHeightOfChildren(ListView.java:1244) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.ListView.onMeasure(ListView.java:1155) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.View.measure(View.java:12752) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4698) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.FrameLayout.onMeasure(FrameLayout.java:293) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.View.measure(View.java:12752) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4698) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1369) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.LinearLayout.measureVertical(LinearLayout.java:660) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.LinearLayout.onMeasure(LinearLayout.java:553) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.View.measure(View.java:12752) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.RelativeLayout.measureChild(RelativeLayout.java:579) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:392) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.View.measure(View.java:12752) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4698) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.FrameLayout.onMeasure(FrameLayout.java:293) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.View.measure(View.java:12752) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4698) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1369) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.LinearLayout.measureVertical(LinearLayout.java:660) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.LinearLayout.onMeasure(LinearLayout.java:553) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.View.measure(View.java:12752) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4698) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.widget.FrameLayout.onMeasure(FrameLayout.java:293) 
03-21 11:47:13.106: E/AndroidRuntime(597): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2265) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.View.measure(View.java:12752) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1074) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2462) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.os.Handler.dispatchMessage(Handler.java:99) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.os.Looper.loop(Looper.java:137) 
03-21 11:47:13.106: E/AndroidRuntime(597): at android.app.ActivityThread.main(ActivityThread.java:4486) 
03-21 11:47:13.106: E/AndroidRuntime(597): at java.lang.reflect.Method.invokeNative(Native Method) 
03-21 11:47:13.106: E/AndroidRuntime(597): at java.lang.reflect.Method.invoke(Method.java:511) 
03-21 11:47:13.106: E/AndroidRuntime(597): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
03-21 11:47:13.106: E/AndroidRuntime(597): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
03-21 11:47:13.106: E/AndroidRuntime(597): at dalvik.system.NativeStart.main(Native Method) 

我ListToGridAdapter低於:

public class ListToGridAdapter extends BaseAdapter implements OnClickListener, OnLongClickListener { 

    /** 
    * The wrapper content --> adapter 
    */ 
    private SimpleAdapter mAdapter = null; 
    /** 
    * The number columns 
    */ 
    private int mColumns = 1; 
    /** 
    * The real onItemClickListener 
    */ 
    private OnGridItemClickListener mGridListener; 
    /** 
    * The real onItemLongClickListener 
    */ 
    private OnGridItemLongClickListener mGridLongClickListener; 

    /** 
    * The Context Object 
    */ 
    private Context mContext; 

    private int sidebarPixals = 0; 
    private int sideBlankPixals = 0; 

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

     if (mColumns == 1) { 
      View child = mAdapter.getView(position, convertView, parent); 
      setOnItemClickListenerIfNeed(child, position, position); 
      setOnItemLongClickListenerIfNeed(child, position, position); 
      // no need 
      return child; 
     } 

     return bindGridView(position, convertView, parent); 
    } 

    protected View bindGridView(int position, View convertView, ViewGroup parent) { 
     ViewGroup root = null; 
     if (convertView == null || !(convertView instanceof ViewGroup)) { 
      root = createRoot(); 
      root.setClickable(false); 
      root.setFocusable(false); 
     } else { 
      root = (ViewGroup) convertView; 
     } 
     // columns = 3 
     // pos --> real pos 
     // 0 --> 0 1 2 
     // 1 --> 3 4 5 
     // 2 --> 6 7 8 
     // so do this 
     return bindView(root, position); 
    } 

    protected ViewGroup bindView(ViewGroup root, int pos) { 

     final int count = mAdapter.getCount(); 
     final int childCount = root.getChildCount(); 

     for (int i = 0; i < mColumns; i++) { 
      // real position 
      int index = mColumns * pos + i; 

      // 不足一行時,直接返回現有狀態 
      if (index == count) { 
       // fix bug : root是有可能是系統緩存的root,這裏直接返回root將導致如果此行數量 
       // 不夠columns,就會使用緩存的root裏的child,爲了避免這個問題,必須 
       // 將緩存的child移除。 
       removeCacheChild(root, index); 
       break; 
      } else if (index > count) { 
       throw new UnknownError("unknowError"); 
      } 

      View child = mAdapter.getView(index, root.getChildAt(i), root); 

      setOnItemLongClickListenerIfNeed(child, pos, index); 
      setOnItemClickListenerIfNeed(child, pos, index); 

      if (childCount == mColumns) { 
       // root已經包含了Item,就沒有必要繼續添加了。 
       continue; 
      } else { 
       if (i == 0 && childCount != 0) { 
        // 如果root已經包含item,但是並不全,這裏就移除重新添加 
        // FIXME 也許還有更好的方案 
        root.removeAllViews(); 
       } 
       LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
         // LinearLayout.LayoutParams.WRAP_CONTENT, 
         (mContext.getResources().getDisplayMetrics().widthPixels - sidebarPixals - sideBlankPixals) 
           /mColumns, 
         LinearLayout.LayoutParams.WRAP_CONTENT); 
       child.setFocusable(true); 
       child.setClickable(true); 
       if (child instanceof ViewGroup) { 
        ((ViewGroup) child) 
          .setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 
       } 
       root.addView(child, lp); 
      } 
     } 
     return root; 
    } 

    /** 
    * remove child view in cache of root 
    */ 
    private void removeCacheChild(ViewGroup root, int index) { 
     int realColumns = (index - 1) % mColumns; 
     int moveCount = (mColumns - 1) - realColumns; 

     for (int i = 0; i < moveCount; i++) { 
      final View child = root.getChildAt((mColumns - 1 - i)); 
      if (child != null) { 
       root.removeView(child); 
      } 
     } 
    } 

    /** 
    * create root for item of ListView 
    */ 
    protected ViewGroup createRoot() { 
     LinearLayout root = new LinearLayout(mContext); 
     root.setOrientation(LinearLayout.HORIZONTAL); 
     LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 
       LayoutParams.WRAP_CONTENT); 
     root.setLayoutParams(lp); 
     return root; 
    } 

    private boolean setOnItemClickListenerIfNeed(View child, int pos, 
      int realPos) { 
     if (mGridListener == null) { 
      return false; 
     } 
     child.setOnClickListener(this); 
     child.setTag(R.id.pos, pos); 
     child.setTag(R.id.realPos, realPos); 
     return true; 
    } 

    private boolean setOnItemLongClickListenerIfNeed(View child, int pos, 
      int realPos) { 
     if (mGridLongClickListener == null) { 
      return false; 
     } 
     child.setOnLongClickListener(this); 
     child.setTag(R.id.pos, pos); 
     child.setTag(R.id.realPos, realPos); 
     return true; 
    } 

    public void setOnItemClickListener(OnGridItemClickListener listener) { 
     this.mGridListener = listener; 
    } 

    public void setOnItemLongClickListener(OnGridItemLongClickListener listener){ 
     this.mGridLongClickListener = listener; 
    } 

    public void setNumColumns(int columns) { 
     this.mColumns = columns; 
    } 

    public int getNumColumns() { 
     return mColumns; 
    } 

    public ListToGridAdapter(Context context, SimpleAdapter adapter) { 
     this.mContext = context; 
     this.mAdapter = adapter; 
     int model = YoutubeAPI.getKindleFireModel(); 

     if (model == 1){ 
      sideBlankPixals = 10 * 2; 
      sidebarPixals = 0; 
     } else if (model == 2){ 
      sideBlankPixals = 10 * 2; 
      sidebarPixals = 60; 
     } else if (model == 3){ 
      sideBlankPixals = (int)(10 * 2 * 1.5); 
      sidebarPixals = 78; 
     } else if (model == 4){ 
      sideBlankPixals = (int)(10 * 2 * 1.5); 
      sidebarPixals = 90; 
     } 

    } 

    @Override 
    public int getCount() { 
     int count = (int) Math.ceil(mAdapter.getCount()/(double) mColumns); 
     return count; 
    } 

    @Override 
    public Object getItem(int position) { 
     return mAdapter.getItem(position); 
    } 

    @Override 
    public long getItemId(int position) { 
     return mAdapter.getItemId(position); 
    } 

    @Override 
    public boolean hasStableIds() { 
     return mAdapter.hasStableIds(); 
    } 

    @Override 
    public void registerDataSetObserver(DataSetObserver observer) { 
     mAdapter.registerDataSetObserver(observer); 
    } 

    @Override 
    public void unregisterDataSetObserver(DataSetObserver observer) { 
     mAdapter.unregisterDataSetObserver(observer); 
    } 

    @Override 
    public boolean areAllItemsEnabled() { 
     return mAdapter.areAllItemsEnabled(); 
    } 

    @Override 
    public boolean isEnabled(int position) { 
     return mAdapter.isEnabled(position); 
    } 

    @Override 
    public int getItemViewType(int position) { 
     return mAdapter.getItemViewType(position); 
    } 

    @Override 
    public int getViewTypeCount() { 
     return mAdapter.getViewTypeCount(); 
    } 

    @Override 
    public boolean isEmpty() { 
     return mAdapter.isEmpty(); 
    } 

    public ListAdapter getWrappedAdapter() { 
     return mAdapter; 
    } 

    public static interface OnGridItemClickListener { 
     public void onItemClick(int pos, int realPos); 
    } 

    public static interface OnGridItemLongClickListener{ 
     public void onItemLongClick(int pos, int realPos); 
    } 

    @Override 
    public void onClick(View v) { 
     if (mGridListener == null) { 
      // no need to feedback 
     } 
     int pos = (Integer) v.getTag(R.id.pos); 
     int realPos = (Integer) v.getTag(R.id.realPos); 

     mGridListener.onItemClick(pos, realPos); 
    } 

    @Override 
    public boolean onLongClick(View v) { 
     if (mGridLongClickListener == null) { 
      // no need to feedback 
     } 
     int pos = (Integer) v.getTag(R.id.pos); 
     int realPos = (Integer) v.getTag(R.id.realPos); 

     mGridLongClickListener.onItemLongClick(pos, realPos); 
     return true; 
    } 

} 
在活動

ListToGridAdapter mAdapter = new ListToGridAdapter(this, mVideoGridviewAdapter); 
mAdapter.setNumColumns(3); 

pullToRefreshListview.setAdapter(mAdapter); 

的mVideoGridviewAdapter是simpleAdapter。

問題在哪裏?它似乎是listview的頁腳,但我不知道如何解決它。

====編輯=====

在活動中,我添加一些的AsyncTask刷新列表視圖。在onPostExecute中,我將一些項目添加到列表視圖中,使列表視圖更長,並將列表視圖的頁腳視圖從View.VISIBLE更改爲View.INVISIBLE,這是否重要?

+0

見我的答案在http://stackoverflow.com/questions/15537097/error-when-removing- from-arraylist/15537383?noredirect = 1#comment22012845_15537383 – 2013-03-21 03:59:10

+0

@HoanNguyen謝謝你的評論,但我的問題不喜歡這個。我的所有日​​志顯示這不是我的代碼導致的問題。也許我在'ListToGridAdapter'中做了'getCount'錯誤。 – Wesley 2013-03-21 04:22:11

+0

是否有一個原因,你沒有使用正常的[GridView](http://developer.android.com/guide/topics/ui/layout/gridview.html)? – dymmeh 2013-03-21 04:31:14

回答

2

我想出了自己。

當更改片段(其中包含listview)時,listview將首先自行清空,然後listview將在滾動時重新索引索引,然後在重新加載listview時,將發生IndexOutOfBoundsException

因此,解決辦法是:重置ListView的適配器破壞時,代碼片斷如下

public void onDestroyView() { 
    if (listview != null && mVideoGridviewAdapter != null) { 
     ListToGridWrapper<GridviewAdapter> mAdapter = new ListToGridWrapper<GridviewAdapter>(getActivity(), mVideoGridviewAdapter); 
     mAdapter.setNumColumns(2); 
     listview.setAdapter(mAdapter); 
    } 
    super.onDestroyView(); 
}