回收视图膨胀不同的行:- 绑定数据时出现异常

Posted

技术标签:

【中文标题】回收视图膨胀不同的行:- 绑定数据时出现异常【英文标题】:Recycle-view inflating different row :- Getting exception while binding the data 【发布时间】:2017-02-19 15:31:33 【问题描述】:

我正在研究具有不同项目膨胀的Recyceview。当我RecycleViewonBindViewHolder 方法上绑定数据时,它不会崩溃.. 但是当我在onBindViewHolder 中绑定数据而不是得到Exception 时,请检查我的代码,让我知道我在哪里做错了。

package com.tv.practise.adapter;

  /**
    Created by Ravindra Kushwaha on 10/10/16.
   */

public class RecycleDataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> 

private Context mContext;
private ArrayList<RecycleBen> data;

public static class SimpleText extends RecyclerView.ViewHolder 
    TextView first_data_tv;

    public SimpleText(View v) 
        super(v);
        this.first_data_tv = (TextView) v.findViewById(R.id.first_data_tv);
    


public   class SimpleImage extends  RecyclerView.ViewHolder 
    ImageView second_data_iv;

    public SimpleImage(View v) 
        super(v);
        this.second_data_iv = (ImageView) v.findViewById(R.id.second_data_iv);
    


public  class SimpleImageWithText extends  RecyclerView.ViewHolder 
    TextView third_data_tv;
    ImageView third_iv;

    public SimpleImageWithText(View v) 
        super(v);
        this.third_data_tv = (TextView) v.findViewById(R.id.third_data_tv);
        this.third_iv = (ImageView) v.findViewById(R.id.third_iv);
    


public RecycleDataAdapter(Context mContext, ArrayList<RecycleBen> data) 
    this.mContext = mContext;
    this.data = data;


@Override
public  RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 

    int listViewItemType = getItemViewType(viewType);
    View itemView;
    if(listViewItemType==1)
    

        itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.recycle_first_item, parent, false);

        return new SimpleText(itemView

        );

    
    else if(listViewItemType==2)
    
        itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.recycle_fsecond_item, parent, false);
        return new SimpleImage(itemView);
    
    else
    
        itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.recycle_third_item, parent, false);
        return new SimpleImageWithText(itemView);
    





@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) 
    RecycleBen bean = data.get(position);

    if(holder.getItemViewType()==1)
    
           /////HERE I AM GETTING THE EXCEPTION WHILE BINDIND DATA
        ((SimpleText)holder).first_data_tv.setText(bean.getName());

    
    else if(holder.getItemViewType()==2)
    

    
    else 
          /////HERE I AM GETTING THE EXCEPTION WHILE BINDIND DATA((SimpleImageWithText)holder).third_data_tv.setText(bean.getName());
    






@Override
public int getItemViewType(int position) 
    return Integer.parseInt(data.get(position).getType_row());


@Override
public int getItemCount() 
    return data.size();
  

异常在我绑定数据时如下:-

3758-3758/com.tv.practise E/androidRuntime﹕ FATAL EXCEPTION: main
    Process: com.tv.practise, PID: 3758
    java.lang.ClassCastException: com.tv.practise.adapter.RecycleDataAdapter$SimpleImageWithText cannot be cast to com.tv.practise.adapter.RecycleDataAdapter$SimpleText
            at com.tv.practise.adapter.RecycleDataAdapter.onBindViewHolder(RecycleDataAdapter.java:101)
            at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5471)
            at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5504)
            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4741)
            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4617)
            at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1994)
            at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1390)
            at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1353)
            at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:574)
            at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3028)
            at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:2625)
            at android.view.View.measure(View.java:18804)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
            at android.view.View.measure(View.java:18804)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
            at android.view.View.measure(View.java:18804)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
            at android.view.View.measure(View.java:18804)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5954)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
            at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2643)
            at android.view.View.measure(View.java:18804)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2112)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1228)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1464)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1119)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6060)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
            at android.view.Choreographer.doCallbacks(Choreographer.java:670)
            at android.view.Choreographer.doFrame(Choreographer.java:606)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
            at android.os.Handler.handleCallback(Handler.java:746)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:148)
            at android.app.ActivityThread.main(ActivityThread.java:5443)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

【问题讨论】:

应该是错的。我删除了我的评论。我正在写另一个。 好的@Joshua .. 等待我们的回复 【参考方案1】:

@Joshua 解决了我的问题.. 对于我在这里发布的其他用户是在RecycleView 中膨胀不同行(3 行) 的代码 它工作正常,请检查以下代码行:- 我在这里发布我的完整代码,请检查:-

这里RecyleClass.java是我的主要课程

package com.tv.practise.recycleview;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import com.tv.practise.R;

import java.util.ArrayList;

/**
 * Created by Ravindra Kushwaha on 10/10/16.
 */
public class RecyleClass extends Activity 

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.recycle_main);

        RecyclerView recycler_vw = (RecyclerView)findViewById(R.id.recycler_vw);


        ArrayList<RecycleBen> arrayList = new ArrayList<>();

        for (int i = 0;i<=25;i++)
        
            RecycleBen bean = new RecycleBen();

            if(i%2==0)
            

                bean.setType_row("1");
                bean.setName("First element");
                bean.setImage_url("http://www.androhub.com/wp-content/uploads/2015/09/staggeredrecyclerview_banner.jpg");
            
            else if(i%3==0)
            
                bean.setType_row("2");
                bean.setName("Second element");
                bean.setImage_url("http://i.stack.imgur.com/snB84.png");
            
            else
            
                bean.setType_row("3");
                bean.setName("Third element");
                bean.setImage_url("http://inducesmile.com/wp-content/uploads/2015/05/gridbanner.jpg");
            

            arrayList.add(bean);

        

        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);

        recycler_vw.setLayoutManager(mLayoutManager);
        recycler_vw.setItemAnimator(new DefaultItemAnimator());
        recycler_vw.setAdapter(new RecycleDataAdapter(this, arrayList));

    

这是 RecyleClass.java 的我的 layout,即 recycle_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_
    android:layout_>


    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_vw"
        android:layout_
        android:layout_
        android:clipToPadding="false"
        />
</LinearLayout>

Gradles 条目用于 RecycleviewCardViewGlide

 // CardView
    compile 'com.android.support:cardview-v7:23.4.0'
    // RecyclerView
    compile 'com.android.support:recyclerview-v7:23.4.0'

    // For the glide libraray
    compile 'com.github.bumptech.glide:glide:3.7.0'

下面是我的gettersetter 类,即RecycleBen.java

package com.tv.practise.recycleview;

/**
 * Created by Ravindra Kushwaha on 10/10/16.
 */
public class RecycleBen 

    private String type_row;
    private String name;
    private String image_url;


    public String getType_row() 
        return type_row;
    

    public void setType_row(String type_row) 
        this.type_row = type_row;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String getImage_url() 
        return image_url;
    

    public void setImage_url(String image_url) 
        this.image_url = image_url;
    

最后是我的适配器类 RecycleDataAdapter.java

package com.tv.practise.adapter;

/**
 * Created by Ravindra Kushwaha on 10/10/16.
 */
public class RecycleDataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> 

    private Context mContext;
    private ArrayList<RecycleBen> data;



    public  class SimpleText extends RecyclerView.ViewHolder 
        TextView first_data_tv;

        public SimpleText(View v) 
            super(v);
            this.first_data_tv = (TextView) v.findViewById(R.id.first_data_tv);
        
    

    public   class SimpleImage extends  RecyclerView.ViewHolder 
        ImageView second_data_iv;
        ProgressBar second_pb;

        public SimpleImage(View v) 
            super(v);
            this.second_data_iv = (ImageView) v.findViewById(R.id.second_data_iv);
            this.second_pb = (ProgressBar)v.findViewById(R.id.second_pb);
        
    

    public  class SimpleImageWithText extends  RecyclerView.ViewHolder 
        TextView third_data_tv;
        ImageView third_iv;
        ProgressBar third_pb;

        public SimpleImageWithText(View v) 
            super(v);
            this.third_data_tv = (TextView) v.findViewById(R.id.third_data_tv);
            this.third_iv = (ImageView) v.findViewById(R.id.third_iv);
            this.third_pb = (ProgressBar)v.findViewById(R.id.third_pb);
        
    

    public RecycleDataAdapter(Context mContext, ArrayList<RecycleBen> data) 
        this.mContext = mContext;
        this.data = data;
    

    @Override
    public  RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 

        View itemView;
        if(viewType==1)
        

            itemView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.recycle_first_item, parent, false);

            return new SimpleText(itemView

            );

        
        else if(viewType==2)
        
            itemView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.recycle_fsecond_item, parent, false);
            return new SimpleImage(itemView);
        
        else
        
            itemView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.recycle_third_item, parent, false);
            return new SimpleImageWithText(itemView);
        



    

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) 
        RecycleBen bean = data.get(position);

        if(holder.getItemViewType()==1)
        

            ((SimpleText)holder).first_data_tv.setText(bean.getName());

        
        else if(holder.getItemViewType()==2)
        
            final SimpleImage simple_holder = (SimpleImage)holder;



            simple_holder.second_pb.setVisibility(View.VISIBLE);
            Glide.with(mContext)
                    .load(bean.getImage_url())
                    .fitCenter()
                    .crossFade()
                    .listener(new RequestListener<String, GlideDrawable>() 
                        @Override
                        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) 
                            if (e instanceof UnknownHostException)
                                simple_holder.second_pb.setVisibility(View.VISIBLE);

                            return false;
                        

                        @Override
                        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) 
                            simple_holder.second_pb.setVisibility(View.GONE);
                            simple_holder.second_data_iv.setVisibility(View.VISIBLE);
                            return false;
                        
                    ).into(simple_holder.second_data_iv);;

        
        else 

            final SimpleImageWithText third_holder = (SimpleImageWithText)holder;

            third_holder.third_data_tv.setText(bean.getName());

            third_holder.third_pb.setVisibility(View.VISIBLE);
            Glide.with(mContext)
                    .load(bean.getImage_url())
                    .fitCenter()
                    .crossFade()
                    .listener(new RequestListener<String, GlideDrawable>() 
                        @Override
                        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) 
                            if (e instanceof UnknownHostException)
                                third_holder.third_pb.setVisibility(View.VISIBLE);

                            return false;
                        

                        @Override
                        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) 
                            third_holder.third_pb.setVisibility(View.GONE);
                            third_holder.third_iv.setVisibility(View.VISIBLE);
                            return false;
                        
                    ).into(third_holder.third_iv);;



        

    




    @Override
    public int getItemViewType(int position) 
        return Integer.parseInt(data.get(position).getType_row());
    

    @Override
    public int getItemCount() 
        return data.size();
    

由于我们对Recycleview 中的不同行进行膨胀,所以我们在这里使用了3 个布局,它们分别为recycle_first_item.xmlrecycle_fsecond_item.xml 和最后一个 recycle_third_item.xml 我一一展示了xml的所有布局,如下:-

recycle_first_item.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_
    android:layout_
    android:layout_gravity="center"
    android:layout_margin="5dp"
    card_view:cardCornerRadius="4dp">

    <LinearLayout
        android:layout_
        android:layout_
        android:orientation="vertical"
        android:gravity="center">

        <TextView
            android:id="@+id/first_data_tv"
            android:layout_
            android:layout_
            android:textColor="@android:color/black"
            android:textSize="25sp"
            android:text="Hello Card" />

    </LinearLayout>

recycle_fsecond_item.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_
    android:layout_
    android:layout_gravity="center"
    android:layout_margin="5dp"
    card_view:cardCornerRadius="4dp">


    <RelativeLayout
        android:layout_
        android:layout_
        >

        <ProgressBar
            android:id="@+id/second_pb"
            android:layout_
            android:layout_
            android:layout_centerInParent="true"
            />

        <ImageView
            android:id="@+id/second_data_iv"
            android:layout_
            android:layout_
            android:textColor="@android:color/black"
            android:layout_centerInParent="true"
            android:visibility="invisible"
            android:src="@drawable/bubble1" />

    </RelativeLayout>

</android.support.v7.widget.CardView>

recycle_third_item.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_
    android:layout_
    android:layout_gravity="center"
    android:layout_margin="5dp"
    card_view:cardCornerRadius="4dp">

    <RelativeLayout
        android:layout_
        android:layout_
        android:orientation="vertical"
        android:gravity="center">

        <TextView
            android:id="@+id/third_data_tv"
            android:layout_
            android:layout_
            android:textColor="@android:color/black"
            android:textSize="25sp"
            android:layout_centerInParent="true"
            android:text="Hello Card" />

        <ProgressBar
            android:id="@+id/third_pb"
            android:layout_
            android:layout_
            android:layout_centerInParent="true"
            android:layout_below="@+id/third_data_tv"
            />

        <ImageView
            android:id="@+id/third_iv"
            android:layout_
            android:layout_below="@+id/third_data_tv"
            android:layout_
            android:src="@drawable/bubble2"
            android:layout_centerInParent="true"
            android:visibility="invisible"
            />

    </RelativeLayout> 
</android.support.v7.widget.CardView>

最后结果如下:-

【讨论】:

完美答案!! 谢谢..大约 4 年后,得到赞赏☺️ 这里是一个基于此代码的演示应用程序仓库的链接:github.com/n-anselm/MultiViewAdapterRecyclerViewDemo【参考方案2】:

原因是onCreateViewHolder(ViewGroup parent, int viewType)。参数是视图类型而不是位置。使用int listViewItemType = getItemViewType(viewType) 是不正确的,因为position 应该传递给getItemViewType

简而言之,你应该直接使用viewType,将onCreateViewHolder中的listViewItemType去掉。

【讨论】:

谢谢@Joshua .. 它工作了.. 现在我接受你的回答并在这里为其他用户发布正确的代码.. 再次感谢:)

以上是关于回收视图膨胀不同的行:- 绑定数据时出现异常的主要内容,如果未能解决你的问题,请参考以下文章

Android ViewBinding 有时会在绑定对象处返回 null,因此在尝试访问视图时出现空指针异常

检查后在 SwiftUI 中将可选绑定设置为 nil 时出现异常

参数/列未绑定将C#应用程序连接到SAP HANA数据库时出现异常

qtudp绑定网卡时出现异常

调用与 btouch 绑定并返回对象的方法时出现异常 System.InvalidCastException。单触错误?

运行 Gradle JUnit 测试时出现“地址已在使用:绑定”异常