回收者视图致命异常:java.lang.ArrayIndexOutOfBoundsException [英] Recycler View Fatal Exception: java.lang.ArrayIndexOutOfBoundsException

查看:107
本文介绍了回收者视图致命异常:java.lang.ArrayIndexOutOfBoundsException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经通过crashlytics获得了此堆栈跟踪.我不知道问题出在哪里.

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

是否可以使用StaggeredGridLayoutManager的任何替代方法来获取诸如布局之类的列表视图.

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;
  }

推荐答案

看起来像您在尝试调用 getAdapterPosition(),而未计算Recycler View布局(可能是由notifyDataSetChanged()调用触发的) ).

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

总是这样处理

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

如果要通过单击ViewHolder来访问适配器中的项目,则应使用getAdapterPosition().请注意,如果已经调用notifyDataSetChanged()并且尚未计算出新的布局,则这些方法可能无法计算适配器的位置.因此,您应谨慎处理这些方法的NO_POSITION或空结果.

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.

更新

现在,您终于发布了一些代码.这是您应该考虑的一些事情.

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

  1. 请勿在onBindViewHolder内部传递最终参数.到触发OnClickListener时,位置并不能保证与您认为的位置相同.这样吧

  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
}

  • 请勿在onBindViewHolder方法内分配任何侦听器.随着视图的回收,您最终会在同一视图中多次设置侦听器.而是将其设置在视图持有人类或如下所示的onCreateViewHolder方法中

  • 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);
    }
    

    或者在ViewHolder类中

    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
                    }
                 }
              });
            }
       }
    

  • 修复以上问题可能会解决您的问题.我强烈建议您查看有关RecyclerView的Google Dev Summit 2015视频.这真的很有趣,他们谈论了RecyclerView的来龙去脉.他们还提到了为什么不在onBinViewHolder内部传递最终参数.点击此处,以查看他们谈论视频的确切时间.

    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.

    这篇关于回收者视图致命异常:java.lang.ArrayIndexOutOfBoundsException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆