2014-09-09 10 views
7

मेरे पास ArrayIndexOutOfBoundsException है जो यादृच्छिक रूप से आता है। ऐसा लगता है कि मेरे notifyDataSetChanged(); के दौरान हो रहा है क्योंकि त्रुटि इतनी यादृच्छिक है क्योंकि यह ठीक से पिन करना मुश्किल हो जाता है कि यह कहां हो रहा है।एंड्रॉइड ArrayIndexOutOfBoundsException और AbsListViewRecycleBin.addScrapView

क्या किसी के पास कस्टम Adaptor के साथ समान समस्याएं हैं?

FATAL EXCEPTION: main 
java.lang.ArrayIndexOutOfBoundsException: length=12; index=12 
    at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:8041) 
    at android.widget.ListView.layoutChildren(ListView.java:1604) 
    at android.widget.AbsListView.onLayout(AbsListView.java:2444) 
    at android.view.View.layout(View.java:15221) 
    at android.view.ViewGroup.layout(ViewGroup.java:4793) 
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677) 
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531) 
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1440) 
    at android.view.View.layout(View.java:15221) 
    at android.view.ViewGroup.layout(ViewGroup.java:4793) 
    at android.widget.FrameLayout.onLayout(FrameLayout.java:448) 
    at android.view.View.layout(View.java:15221) 
    at android.view.ViewGroup.layout(ViewGroup.java:4793) 
    at android.widget.FrameLayout.onLayout(FrameLayout.java:448) 
    at android.view.View.layout(View.java:15221) 
    at android.view.ViewGroup.layout(ViewGroup.java:4793) 
    at android.widget.FrameLayout.onLayout(FrameLayout.java:448) 
    at android.view.View.layout(View.java:15221) 
    at android.view.ViewGroup.layout(ViewGroup.java:4793) 
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677) 
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531) 
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1440) 
    at android.view.View.layout(View.java:15221) 
    at android.view.ViewGroup.layout(ViewGroup.java:4793) 
    at android.widget.FrameLayout.onLayout(FrameLayout.java:448) 
    at android.view.View.layout(View.java:15221) 
    at android.view.ViewGroup.layout(ViewGroup.java:4793) 
    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2260) 
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2007) 
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1249) 
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6364) 
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:791) 
    at android.view.Choreographer.doCallbacks(Choreographer.java:591) 
    at android.view.Choreographer.doFrame(Choreographer.java:561) 
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:777) 
    at android.os.Handler.handleCallback(Handler.java:730) 
    at android.os.Handler.dispatchMessage(Handler.java:92) 
    at android.os.Looper.loop(Looper.java:137) 
    at android.app.ActivityThread.main(ActivityThread.java:5455) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:525) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) 
    at dalvik.system.NativeStart.main(Native Method) 




public class CarUpfitScanvinadapter extends BaseAdapter{ 
    @SuppressWarnings("unused") 
    private final String TAG = this.getClass().getSimpleName(); 
    private Activity mActivity; 
    private ArrayList<CarUpfitModel> mData; 
    private static LayoutInflater sInflater = null; 
    public int height = 0; 
    public int heightSet = 0; 
    private CarUpfitModelForm mForm; 
    private ScanlistListener mCallback; 

    public CarUpfitScanvinadapter(Activity a, ArrayList<CarUpfitModel> d, Resources resLocal){ 
     mActivity = a; 
     mData = d; 
     sInflater = (LayoutInflater)mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    } 

    public void removeItem(int i){ 
     mData.remove(i); 
     this.notifyDataSetChanged(); 
    } 

    @Override 
    public int getCount() { 
     Log.v(TAG, "getCount"); 
     if(mData.size()<=0) return 1; 
     return mData.size(); 
    } 

    @Override 
    public boolean hasStableIds(){ 
     return false; 
    } 

    @Override 
    public int getViewTypeCount() {     
     return getCount(); 
    } 

    @Override 
    public CarUpfitModel getItem(int position) { 
     return mData.get(position); 
    } 

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

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

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View vi = convertView; 
     if(convertView == null){ 
      vi = sInflater.inflate(R.layout.subaruupfitscanlistview, parent, false); 
      mForm = new CarUpfitModelForm(); 
      mForm.setllScanlist((LinearLayout) vi.findViewById(R.id.llScanlist)); 
      mForm.getllScanlist().setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,heightSet)); 
      mForm.setllheightset((LinearLayout) vi.findViewById(R.id.llheightset)); 
      mForm.setetModel((EditText) vi.findViewById(R.id.etModel)); 
      mForm.settvScanlistvin((TextView) vi.findViewById(R.id.tvScanlistvin)); 
      mForm.settvScanlistdate((TextView) vi.findViewById(R.id.tvScanlistdate)); 
      mForm.setcbGbkit((CheckBox) vi.findViewById(R.id.cbGbkit)); 
      mForm.setcbFltmat((CheckBox) vi.findViewById(R.id.cbFltmat)); 
      mForm.setcbFlmatbrk((CheckBox) vi.findViewById(R.id.cbFlmatbrk)); 
      mForm.setcbEyesight((CheckBox) vi.findViewById(R.id.cbEyesight)); 
      mForm.setcbTrnkpan((CheckBox) vi.findViewById(R.id.cbTrnkpan)); 
      mForm.setcbIntmirror((CheckBox) vi.findViewById(R.id.cbIntmirror)); 
      mForm.setcbExtmirror((CheckBox) vi.findViewById(R.id.cbExtmirror)); 
      mForm.setcbPzevbadge((CheckBox) vi.findViewById(R.id.cbPzevbadge)); 
      mForm.setivDelete((ImageView) vi.findViewById(R.id.ivDelete)); 
      mForm.setivSave((ImageView) vi.findViewById(R.id.ivSave)); 
      mForm.getivSave().setTag(mForm); 
      vi.setTag(mForm); 
     }else{ 
      mForm = (CarUpfitModelForm) vi.getTag(); 
     } 
     mForm.getllScanlist().setOnClickListener(new OnItemClickListener(position, CarUpfit.ITEM_CLICK)); 
     if(mData.size()<=0){ 
      mForm.puttvScanlistvin("No Data"); 
     }else{ 
      mForm.puttvScanlistvin(getItem(position).getVin()); 
      mForm.puttvScanlistdate(getItem(position).getDate()); 
      mForm.setId(getItem(position).getid()); 
      mForm.putjson(getItem(position).getData()); 
      mForm.getivSave().setOnClickListener(new OnItemClickListener(position, CarUpfit.ITEM_UPDATE)); 
      mForm.getivDelete().setOnClickListener(new OnItemClickListener(position, CarUpfit.ITEM_REMOVE)); 
     } 
     return vi; 
    } 

    private class OnItemClickListener implements OnClickListener{ 
     private int mPosition; 
     private int mType; 

     OnItemClickListener(int position, int type){ 
      mPosition = position; 
      mType = type; 
     } 
     @Override 
     public void onClick(View v) { 
      mCallback.scanlistclick(v, mPosition, mType); 
     } 
    } 

    public void setimplements(CarUpfit sl) { 
     try { 
      mCallback = (ScanlistListener) sl; 
     } catch (ClassCastException e) { 
      throw new ClassCastException("CarUpfit must implement ScanlistListener"); 
     } 
    } 

    public interface ScanlistListener{ 
     public void scanlistclick(View v, int position, int type); 
    } 
} 

संपादन

मैं एनीमेशन कि सूची आइटम का विस्तार के साथ आइटम की एक सूची है। यही कारण है कि मैंने getViewTypeCount() पर ओवरराइड किया है। यदि कोई उपयोगकर्ता किसी आइटम को खोलता है तो मैं इसे ओवरराइड नहीं करता हूं, यह दूसरों को भी खोल देगा।

आइटम का स्क्रीन शॉट बंद कर दिया: आइटम के

items closed

स्क्रीन शॉट खुला:

enter image description here

+1

अपने एडाप्टर कोड – bhargavg

+0

@bhargavg को पेस्ट करने की आवश्यकता है। – K3NN3TH

+0

हालांकि समस्या से संबंधित नहीं है, फिर भी आप 'हैस्टेबल आईडी()' से 'झूठी' क्यों लौट रहे हैं? – bhargavg

उत्तर

14

आप getViewTypeCount() और getItemViewType() पर हावी नहीं होना चाहिए यदि आपके सभी सूची आइटम वर्दी कर रहे हैं, या कम से कम उन्हें 1 और 0 क्रमशः वापस कर दें।

कि आप उन्हें जैसे ही किया, सब से पहले अधिभावी करके आप ListView को देखते-रीसाइक्लिंग तंत्र को बाधित, और दूसरा यह शायद आप वर्णित दुर्घटना, क्योंकि जब आप के प्रकार सूची के मध्य से किसी आइटम को निकालने, सुराग हटाए जाने के बाद विचार बदल गए।

अद्यतन: वास्तव में, यह क्या हो रहा है यह है: ListView केवल setAdapter() में एडाप्टर पर getViewTypeCount() कॉल करता है और है कि आकार का एक आंतरिक सरणी पैदा करता है। तो यदि आप बाद में विचार जोड़ते हैं और आपके getItemViewType() उस आकार से अधिक या उसके बराबर एक इंडेक्स लौटाते हैं, तो आपको ArrayIndexOutOfBoundsException मिलता है।

अद्यतन 2: यदि आपको विस्तारणीय सूची दृश्य की आवश्यकता है, तो बस ExpandableListView का उपयोग करें।

अद्यतन 3: ठीक है, मैं पूरी तरह से समझाऊंगा जैसा मैं कर सकता हूं।

स्क्रीन से दृश्य खोलने का कोई कारण नहीं है। ListView रीसाइक्लिंग करने और अवरोध करने के लिए डिज़ाइन किया गया है, यह 99.9% समय में अनियंत्रित है, और आपका मामला 0.01% शेष नहीं है।

आपके एडाप्टर को सभी विवरण याद रखना चाहिए और सूची दृश्य को स्क्रॉल होने पर नए दिखाई देने वाले विचारों को पॉप्युलेट करना चाहिए।

अपने मामले में आप विचारों के दो प्रकार है - खुला और बंद कर दिया है, तो getViewTypeCount() 2 लौटना चाहिए और getItemViewType()0 या 1 दृश्य बंद कर दिया है या खुला है जो इस पर निर्भर लौटना चाहिए।

getView() में, convertView शून्य है, तो आपको उस स्थिति के लिए getItemViewType() रिटर्न के आधार पर इसे बनाना चाहिए। और यदि यह शून्य नहीं है, तो आप गारंटी देते हैं कि यह उन विचारों में से एक है जिन्हें आपने पहले उसी प्रकार के लिए बनाया था।

// ListView.java 
public void setAdapter(ListAdapter adapter) { 
    ... 
    // This is the only call to getViewTypeCount() 
    mRecycler.setViewTypeCount(mAdapter.getViewTypeCount()); 
    ... 
} 

// AbsListView.java 
public void setViewTypeCount(int viewTypeCount) { 
    ... 
    // Here it creates the array of given size 
    ArrayList<View>[] scrapViews = new ArrayList[viewTypeCount]; 
    ... 
    mViewTypeCount = viewTypeCount; 
    mScrapViews = scrapViews; 
} 

void addScrapView(View scrap, int position) { 
    final int viewType = lp.viewType; 
    ... 
    // And here you get ArrayIndexOutOfBoundsException 
    mScrapViews[viewType].add(scrap); 
} 
+0

मैं बाद में विचार जोड़ रहा हूं, इसलिए मुझे अतिरिक्त दृश्यों के getItemViewType() को बताने की आवश्यकता है। त्रुटि भी यादृच्छिक है, कुछ बार मैं 20 या अधिक जोड़ने में सक्षम हूं और कोई त्रुटि नहीं है। दूसरी बार मैं 2 जोड़ता हूं और एक त्रुटि प्राप्त करता हूं। – K3NN3TH

+0

विचार जोड़ने के साथ आपका क्या मतलब है? आप केवल सरणी सूची में जोड़ सकते हैं। और क्या वे किसी अन्य प्रकार के 'विचार' हैं? आपने यह स्पष्ट नहीं किया कि आप व्यू टाइप गिनती के साथ क्यों फिसलते हैं जहां आप पर एक दृश्य प्रकार है। – greenapps

+0

@ K3NN3TH फिर से, आपके पास केवल एक ही प्रकार के विचार हैं, इसलिए 'getViewTypeCount()' वापस लौटना चाहिए, इससे कोई फर्क नहीं पड़ता कि आपके पास कितने विचार हैं। –

0

आपको लगता है कि अनुक्रमणिका सीमा से सूचित के साथ होता है:

और यहाँ दुर्घटना जो होता है यदि आपके getItemViewType() रिटर्न बड़ी संख्या (मैं एपीआई 19 के लिए सूत्रों का कहना है की चर्चा करते हुए हूँ) मनमाने ढंग से की बात है डेटासेट बदल गया। मैं सहमत हूँ। उदाहरण के लिए जब आप कोई आइटम हटाते हैं। सभी आइटम आइटम पर श्रोताओं पर क्लिक करें, उस आइटम के बाद गलत mPosition मान होगा।

0

यह तब भी होता है जब आपका getItemViewType getViewTypeCount के आकार से अधिक पूर्णांक देता है, इसलिए वे सूचकांक की तरह हैं। जैसे getViewTypeCount 2 को 0 और 1.

संबंधित मुद्दे