Recycler View Fatal Exception: java.lang.ArrayIndexOutOfBoundsException

℡╲_俬逩灬. 提交于 2019-12-05 18:20:33

问题


I have got this stack trace though crashlytics. I have no idea where the issue is.

Is there any alternative of StaggeredGridLayoutManager that I can use to get a listview like layout.

Fatal Exception: java.lang.ArrayIndexOutOfBoundsException: start < 0 || end > len. start=-1, end=11, len=11
   at java.util.Arrays.checkStartAndEnd(Arrays.java:1745)
   at java.util.Arrays.fill(Arrays.java:803)
   at android.support.v7.widget.StaggeredGridLayoutManager$LazySpanLookup.invalidateAfter(SourceFile:2404)
   at android.support.v7.widget.StaggeredGridLayoutManager.handleUpdate(SourceFile:1373)
   at android.support.v7.widget.StaggeredGridLayoutManager.onItemsRemoved(SourceFile:1327)
   at android.support.v7.widget.RecyclerView$6.dispatchUpdate(SourceFile:725)
   at android.support.v7.widget.RecyclerView$6.onDispatchFirstPass(SourceFile:716)
   at android.support.v7.widget.AdapterHelper.dispatchFirstPassAndUpdateViewHolders(SourceFile:316)
   at android.support.v7.widget.AdapterHelper.dispatchAndUpdateViewHolders(SourceFile:302)
   at android.support.v7.widget.AdapterHelper.applyRemove(SourceFile:182)
   at android.support.v7.widget.AdapterHelper.preProcess(SourceFile:103)
   at android.support.v7.widget.RecyclerView.processAdapterUpdatesAndSetAnimationFlags(SourceFile:2767)
   at android.support.v7.widget.RecyclerView.onMeasure(SourceFile:2538)
   at android.view.View.measure(View.java:16521)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5134)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
   at android.view.View.measure(View.java:16521)
   at android.support.v4.view.ViewPager.onMeasure(SourceFile:1489)
   at android.view.View.measure(View.java:16521)
   at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:719)
   at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:455)
   at android.view.View.measure(View.java:16521)
   at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:719)
   at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:455)
   at android.view.View.measure(View.java:16521)
   at android.support.v4.widget.DrawerLayout.onMeasure(SourceFile:940)
   at android.view.View.measure(View.java:16521)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5134)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
   at android.support.v7.widget.ContentFrameLayout.onMeasure(SourceFile:135)
   at android.view.View.measure(View.java:16521)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5134)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
   at android.view.View.measure(View.java:16521)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5134)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
   at android.view.View.measure(View.java:16521)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5134)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
   at android.view.View.measure(View.java:16521)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5134)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
   at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2331)
   at android.view.View.measure(View.java:16521)
   at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1925)
   at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1117)
   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1299)
   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1004)
   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5739)
   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
   at android.view.Choreographer.doCallbacks(Choreographer.java:574)
   at android.view.Choreographer.doFrame(Choreographer.java:544)
   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
   at android.os.Handler.handleCallback(Handler.java:733)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:136)
   at android.app.ActivityThread.main(ActivityThread.java:5380)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:515)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:970)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:786)
   at dalvik.system.NativeStart.main(NativeStart.java)

This is what I am doing to handle click listeners in one of the adapter

     @Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
  holder.relative.setClickable(true);

    holder.relative.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            if (itemClickListener != null)
                itemClickListener.onClick(v, position);
            else
                AppConfig.log("itemClickLestener was null");
        }
    });

    holder.relative.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            if (itemClickListener != null)
                itemClickListener.onLongClick(v, position);
            return true;
        }
    });
  return view;
  }

回答1:


Looks like you were trying to call getAdapterPosition() while Recycler View layouts are not calculated (possibly triggered by a notifyDataSetChanged() call).

always handle it like this

final int position = getAdapterPosition();
if(positon != RecyclerView.NO_POSITION){
    // you can trust the adapter position
    // do whatever you intend to do with this position
}

The documentation clearly states the following

if you want to access the item in the adapter on a ViewHolder click, you should use getAdapterPosition(). Beware that these methods may not be able to calculate adapter positions if notifyDataSetChanged() has been called and new layout has not yet been calculated. For this reasons, you should carefully handle NO_POSITION or null results from these methods.

UPDATE

Now that you have finally posted some code. here are some things you should consider.

  1. Do not pass final parameters inside onBindViewHolder. By the time the OnClickListener is fired the position is not guaranteed to be the same as you think it would be. So do this

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.relative.setClickable(true);
        //do other stuff
    }
    
  2. DO NOT assign any listeners inside onBindViewHolder method. As the view gets recycled you end up setting listeners multiple times to the same view. Instead, set it inside the view holder class or onCreateViewHolder method like below

    @Override
    public MyViewHolder onCreateViewHolder (ViewGroup parent, int viewType) {
        View myView = LayoutInflater.from(parent.getContext())
                            .inflate(R.layout.my_layout, parent, false);
    
        //setting listeners on creation
        myView.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                final int position = getAdapterPosition();
                if(position != RecyclerView.NO_POSITION){
                    //do whatever you want with the clicked position
                }
            }
        });
    
       //return the view holder
       return new MyViewHolder(myView);
    }
    

    Or in the ViewHolder class

    public class MyViewHolder extends RecyclerView.ViewHolder {
    
         public MyViewHolder(View itemView) {
             super(itemView);
    
             //setting listeners inside viewHolder class
             itemView.setOnClickListener(new View.OnClickListener(){
                 @Override
                 public void onClick(View v) {
                    final int position = getAdapterPosition();
                    if(position != RecyclerView.NO_POSITION){
                        //do whatever you want with the clicked position
                    }
                 }
              });
            }
       }
    

Fixing the above may fix your problem. I highly recommend you to check the Google Dev Summit 2015 video about RecyclerView. It is really interesting and they talk about the ins and outs of the RecyclerView. They also mention why not to pass final parameters inside onBinViewHolder. Click here to check out the exact moment in the video in which they talk about it.




回答2:


Mostly this error will be occuring in your on bindview where you will be using the data of your arraylist. Make sure you have used position -1 value of the arraylist.



来源:https://stackoverflow.com/questions/35577548/recycler-view-fatal-exception-java-lang-arrayindexoutofboundsexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!