ClassCastException / ArrayIndexOutOfBoundsException试图让RecyclerView处理多种类型的viewholder

时间:2015-05-31 22:34:29

标签: android android-recyclerview

我的RecyclerView出了问题。让我详细解释一下这个问题。我尝试使用四种不同的子视图实现RecylerView。我按照“Double Wong”的方法进行了操作。所以基本上我从一个主ViewHolder扩展了四个ViewHolder,在onCreateViewHolder()我选择应该初始化哪一个。为此,我重写了getItemViewType()方法。它工作正常,只要所有子类型都是类型0.(类型0表示该项不在数据库中,类型1 - 3表示数据库中有不同的标志)。

有时我会得到 ArrayIndexOutOfBoundsException ,有时它是 ClassCastException 我无法找出模式。 这是我的代码,我做了一些削减,使其更短。

片段

public class SucheSerienFragment extends Fragment {
...
    public List<Pair<SerieInfo, Integer>> listTvShows;
    private SerieCardViewSucheAdapter serieCardViewSucheAdapter;
...

private class LoadSerie extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... search) {
           ...
                        int type;
                        if (db.checkSerie(serieInfo)) {
                            serieInfo = db.getSerieByName(serieInfo.getName());
                            if (serieInfo.getArchivFlag() == 0){
                                type = SucheMainViewHolder.TYPE_AT_WATCHLIST;
                            } else if (serieInfo.getArchivFlag() == 1) {
                                type = SucheMainViewHolder.TYPE_PAUSIERT;
                            } else if (serieInfo.getArchivFlag() == 2) {
                                type = SucheMainViewHolder.TYPE_ABGESCHLOSSEN;
                            }  else {
                                type = SucheMainViewHolder.TYPE_SEARCH;
                        } } else {
                            type = SucheMainViewHolder.TYPE_SEARCH;
                        }

                        final SerieInfo finalSerieInfo = serieInfo;
                        final int finalType = type;

                        getActivity().runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                listTvShows.add(new Pair(finalSerieInfo, finalType));
                                serieCardViewSucheAdapter.notifyItemInserted(serieCardViewSucheAdapter.getItemCount() - 1);
                            }
                        });
                    }
                }
            } catch (TVDBOutboundConnectionException e1) {
                Log.e(TAG, "Es konnte keine Verbindung aufgebaut werden");
                Log.e(TAG, "Error" + e1);
                e1.printStackTrace();
            }
            return "Executed";
        }

        @Override
        protected void onPostExecute(String string) {
            Log.d(TAG, "onPostExecute");
            progressBarLoadSerie.setVisibility(View.GONE);

            if (listTvShows.isEmpty()) {
                Toast.makeText(getActivity(), "Keine Serie gefunden", Toast.LENGTH_SHORT).show();
                nothingFoundFrameLayout.setVisibility(View.VISIBLE);
            }

        }

        @Override
        protected void onPreExecute() {
            Log.d(TAG, "onPreExecute");
            progressBarLoadSerie.setVisibility(View.VISIBLE);
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            Log.d(TAG, "onPrograessUpdate");
        }
    }

SucheMainViewHolder

public class SucheMainViewHolder extends RecyclerView.ViewHolder{
        public static final int TYPE_SEARCH = 0;
        public static final int TYPE_AT_WATCHLIST = 1;
        public static final int TYPE_PAUSIERT= 2;
        public static final int TYPE_ABGESCHLOSSEN= 3;


        public SucheMainViewHolder(View itemView) {
            super ( itemView );
        }
    }

SucheAbgeschlossenHolder

public class SucheAbgeschlossenHolder extends SucheMainViewHolder {
    public TextView tvSerienName;
    public TextView tvCurrentEpisode;
    public ImageView tvSerienImage;
    public RelativeLayout linearBackground;
    public ImageView imgViewSerie;
    public ImageButton playButton;
    public ImageButton deleteButton;
    public ImageButton abschliesButton;

    public SucheAbgeschlossenHolder(View v) {
        super(v);
        tvSerienName = (TextView) v.findViewById(R.id.tvSerienName);
        tvCurrentEpisode = (TextView) v.findViewById(R.id.tvSerienOverview);
        tvSerienImage = (ImageView) v.findViewById(R.id.imgViewSerie);
        linearBackground = (RelativeLayout) v.findViewById(R.id.rla);
        playButton = (ImageButton) v.findViewById(R.id.playImageButton);
        deleteButton = (ImageButton) v.findViewById(R.id.deleteImageButton);
        abschliesButton = (ImageButton) v.findViewById(R.id.abschliesenImageButton);

        imgViewSerie = (ImageView) v.findViewById(R.id.imgViewSerie);
    }
}

SuchePausiertHolder

SuchePausiertHolder extends SucheMainViewHolder {

    public TextView tvSerienName;
    public TextView tvCurrentEpisode;
    public ImageView tvSerienImage;
    public RelativeLayout linearBackground;
    public ImageView imgViewSerie;
    public ImageButton playButton;
    public ImageButton deleteButton;
    public ImageButton abschliesButton;

    public SuchePausiertHolder(View v) {
        super(v);
        tvSerienName = (TextView) v.findViewById(R.id.tvSerienName);
        tvCurrentEpisode = (TextView) v.findViewById(R.id.tvSerienOverview);
        tvSerienImage = (ImageView) v.findViewById(R.id.imgViewSerie);
        linearBackground = (RelativeLayout) v.findViewById(R.id.rla);
        playButton = (ImageButton) v.findViewById(R.id.playImageButton);
        deleteButton = (ImageButton) v.findViewById(R.id.deleteImageButton);
        abschliesButton = (ImageButton) v.findViewById(R.id.abschliesenImageButton);

        imgViewSerie = (ImageView) v.findViewById(R.id.imgViewSerie);
    } 

}

SucheSerieViewHolder

public class SucheSerieViewHolder extends SucheMainViewHolder{


         public TextView tvSerienName;
         public TextView tvSerienOverview;
         public TextView tvRating;
         public ImageView tvSerienImage;
         public  ImageButton btnAddSerie;
         public  LinearLayout linearSerienSucheBackground;

        public SucheSerieViewHolder(View v) {
            super(v);
            tvSerienName = (TextView) v.findViewById(R.id.tvSerienName);
            tvSerienOverview = (TextView) v.findViewById(R.id.tvSerienOverview);
            tvSerienImage = (ImageView) v.findViewById(R.id.imgViewSerie);
            btnAddSerie = (ImageButton) v.findViewById(R.id.btnAddSerie);
            linearSerienSucheBackground = (LinearLayout) v.findViewById(R.id.linearSerienSuche);
            tvRating = (TextView) v.findViewById(R.id.tvRating);
        }

}

SucheWatchedHolder

  public class SucheWatchedHolder extends SucheMainViewHolder {
        public TextView tvSerienName;
        public TextView tvCurrentEpisode;
        public ImageView tvSerienImage;
        public View btnNext;
        public RelativeLayout linearBackground;
        public ImageView imgViewSerie;

        public SucheWatchedHolder(View v) {
            super(v);
            tvSerienName = (TextView) v.findViewById(R.id.tvSerienName);
            tvCurrentEpisode = (TextView) v.findViewById(R.id.tvSerienOverview);
            tvSerienImage = (ImageView) v.findViewById(R.id.imgViewSerie);
            btnNext = (View) v.findViewById(R.id.btnNext);
            linearBackground = (RelativeLayout) v.findViewById(R.id.rla);
            imgViewSerie = (ImageView) v.findViewById(R.id.imgViewSerie);
        }  }

SerieCardViewSucheAdapter

 @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) >{
        LayoutInflater mInflater = LayoutInflater.from ( >viewGroup.getContext () );

        int type = getItemViewType(viewType);
        switch (type) {
            case SucheMainViewHolder.TYPE_SEARCH:
                ViewGroup vSuche = ( ViewGroup ) mInflater.inflate ( >R.layout.cardview_serie_suche, viewGroup, false );
                SucheSerieViewHolder vhSuche = new SucheSerieViewHolder ( >vSuche );
                return vhSuche;
            default:
                vSuche = ( ViewGroup ) mInflater.inflate ( >R.layout.cardview_serie_suche, viewGroup, false );
                vhSuche = new SucheSerieViewHolder ( vSuche );
                return vhSuche;
            case SucheMainViewHolder.TYPE_AT_WATCHLIST:
                ViewGroup vSucheWatched = ( ViewGroup ) mInflater.inflate ( >R.layout.cardview_serie, viewGroup, false );
                SucheWatchedHolder vhSucheWatched = new SucheWatchedHolder >( vSucheWatched );
                return vhSucheWatched;
            case SucheMainViewHolder.TYPE_PAUSIERT:
                ViewGroup vSuchePausiert = ( ViewGroup ) mInflater.inflate >( R.layout.cardview_serie_pausiert, viewGroup, false );
                SuchePausiertHolder vhSuchePausiert = new >SuchePausiertHolder ( vSuchePausiert );
                return vhSuchePausiert;
            case SucheMainViewHolder.TYPE_ABGESCHLOSSEN:
                ViewGroup vSucheAbgeschlossen = ( ViewGroup ) >mInflater.inflate ( R.layout.cardview_serie_abgeschlossen, viewGroup, false );
                SucheAbgeschlossenHolder vhSucheAbgeschlossen= new >SucheAbgeschlossenHolder( vSucheAbgeschlossen );
                return vhSucheAbgeschlossen;

        }



    }
...
     @Override
        public void onBindViewHolder(ViewHolder viewHolder, final int position) {
            final SerieInfo serieInfo = listSerieInfo.get(position).first;
            if (viewHolder == null) {
                return;
            }
            switch (viewHolder.getItemViewType()) {
                default:
                   ...
                    return;
                case SucheMainViewHolder.TYPE_SEARCH:
                  ...
                    return;
                case SucheMainViewHolder.TYPE_AT_WATCHLIST:
                    ...
             return;
                case SucheMainViewHolder.TYPE_PAUSIERT:
                   ...
                    return;
                case SucheMainViewHolder.TYPE_ABGESCHLOSSEN:
                   ...
                    return;
            }


         }

...

     @Override
         public int getItemViewType(int position) {
             return listSerieInfo.get(position).second;
         }

IndexOutOfBoundsException异常

06-01 00:49:17.327  23289-23289/com.turnonandroid.seriencounter E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.turnonandroid.seriencounter, PID: 23289
    java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
            at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
            at java.util.ArrayList.get(ArrayList.java:308)
            at com.turnonandroid.serienmanager.Adapter.SerieCardViewSucheAdapter.getItemViewType(SerieCardViewSucheAdapter.java:390)
            at com.turnonandroid.serienmanager.Adapter.SerieCardViewSucheAdapter.onCreateViewHolder(SerieCardViewSucheAdapter.java:359)
            at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:5062)
            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4368)
            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4278)
            at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1947)
            at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1359)
            at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1322)
            at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:556)
            at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2673)
            at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2971)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1070)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1070)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:335)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:272)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:335)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:272)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1070)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:335)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:272)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.support.v7.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:493)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:335)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:272)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1707)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1561)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1470)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:335)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:272)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:907)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:335)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:272)
            at android.view.View.layout(View.java:16552)
            at android.view.ViewGroup.layout(ViewGroup.java:5355)
            at android.view.ViewRootImpl.performLayout(ViewRoo

ClassCastException异常

06-01 00:56:09.436  27453-27453/com.turnonandroid.seriencounter E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.turnonandroid.seriencounter, PID: 27453
    java.lang.ClassCastException: com.turnonandroid.serienmanager.SucheSerieViewHolder cannot be cast to com.turnonandroid.serienmanager.SucheWatchedHolder
            at com.turnonandroid.serienmanager.Adapter.SerieCardViewSucheAdapter.onBindViewHolder(SerieCardViewSucheAdapter.java:167)
            at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5084)
            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4385)
            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4278)
            at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1947)
            at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1359)
            at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1322)
            at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1150)
            at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1007)
            at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1355)
            at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:2209)
            at android.view.View.dispatchTouchEvent(View.java:9244)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2536)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2229)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2542)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2243)
            at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2392)
            at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1730)
            at android.app.Activity.dispatchTouchEvent(Activity.java:2710)
            at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59)
            at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2353)
            at android.view.View.dispatchPointerEvent(View.java:9439)
            at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4181)
            at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4047)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3593)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3646)

感谢您阅读并思考我的问题。

2 个答案:

答案 0 :(得分:0)

好的,关于IndexOutOfBoundsException,您应该检查适配器中的getItemCount()。如果您在listSerieInfo.get(position)中呼叫getViewType(),则该方法应如下所示:

return listSerieInfo != null ? listSerieInfo.size() : 0;

关于ClassCastException,您必须将default中的onBindViewHolder选项移到底部。应该永远在那里。

答案 1 :(得分:0)

所以我通过不同的方式修复了问题。因此,不是添加不同种类的ViewHolders,而是只有一种。其中包括各种ViewHolders(在布局中),但可见性为GONE。在onBindViewHolder()方法中,我检查应该显示哪种类型,并将可见性设置为VISIBLE。这可能不是最好的方式(可能是最糟糕的),但对我来说它的工作。