RecyclerView 中的捆绑问题

Posted

技术标签:

【中文标题】RecyclerView 中的捆绑问题【英文标题】:Bundle Issues in RecyclerView 【发布时间】:2018-07-08 07:06:09 【问题描述】:

尝试将我的包放入我的意图中时遇到错误onClickListener()RecyclerView CustomViewHolder

java.lang.NullPointerException: 尝试调用虚方法 'void android.os.Bundle.putString(java.lang.String, java.lang.String)' 在一个 空对象引用

我也尝试创建一个新包而不是使用附加功能,但得到与上述相同的错误。奇怪的是,putExtras() 方式适用于一个变量,可以正确传递,但可惜我有大约 8 个不同的变量要插入辅助页面。

代码如下:

    public void onClick(View view) 
    intent = new Intent(itemView.getContext(), CardActivity.class);
    extras = intent.getExtras();
        extras.putString(CARD_IMG, cardList.Basic.get(getAdapterPosition()).getImg());
        extras.putString(CARD_FLAVOR, cardList.Basic.get(getAdapterPosition()).getFlavor());
        extras.putString(CARD_TEXT, cardList.Basic.get(getAdapterPosition()).getText());
        extras.putString(CARD_TYPE, cardList.Basic.get(getAdapterPosition()).getType());
        extras.putString(CARD_ARTIST, cardList.Basic.get(getAdapterPosition()).getArtist());
        extras.putString(CARD_SET, cardList.Basic.get(getAdapterPosition()).getCardSet());
        extras.putString(CARD_RARITY, cardList.Basic.get(getAdapterPosition()).getRarity());
        extras.putString(CARD_NAME, cardList.Basic.get(getAdapterPosition()).getName());
    intent.putExtras(extras);
    itemView.getContext().startActivity(intent);

我们将不胜感激任何正确方向的帮助或推动。

提前谢谢!

编辑:我在下面包含了完整的文件,以防万一。感谢大家到目前为止的回复,非常感谢。

    public class RecyclerAdaptor extends RecyclerView.Adapter<RecyclerAdaptor.CustomViewHolder> 
//for bundle keys
private static final String CARD_FLAVOR = "CARD_FLAVOR";
private static final String CARD_TYPE = "CARD_TYPE";
private static final String CARD_ARTIST = "CARD_ARTIST";
private static final String CARD_SET = "CARD_SET";
private static final String CARD_RARITY = "CARD_RARITY";
private static final String CARD_NAME = "CARD_NAME";
private static final String CARD_IMG = "CARD_IMG";
private static final String CARD_TEXT = "CARD_TEXT";

private static Intent intent;
public static Bundle extras;
public static CardList cardList;

public RecyclerAdaptor(CardList cardList) 
    this.cardList = cardList;


@Override
//Number of Items
public int getItemCount() 
    return cardList.Basic.size();



@Override
public RecyclerAdaptor.CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_row, parent, false);
    CustomViewHolder holder = new CustomViewHolder(v);
    return holder;


@Override
public void onBindViewHolder(RecyclerAdaptor.CustomViewHolder holder, int position) 

    final Card card = cardList.Basic.get(position);
    String cost = "0";
    // Could have made values protected in class, but meh
    holder.cardName.setText(card.getName());
    holder.cardText.setText(card.getText());
    holder.cardFlavor.setText(card.getFlavor());

    // Handles dust value of card
    if (card.getRarity() != null) 
        switch (card.getRarity()) 
            case "Common": cost = "40";
                break;
            case "Rare": cost = "100";
                break;
            case "Epic": cost = "400";
                break;
            case "Legendary": cost = "1600";
                break;
        
    

    holder.cardCost.setText(cost);
    Picasso.with(holder.cardImg.getContext()).load(card.getImg()).into(holder.cardImg);



public static class CustomViewHolder extends RecyclerView.ViewHolder 

    private TextView cardName;
    private TextView cardText;
    private TextView cardFlavor;
    private TextView cardCost;
    private GifImageView cardImg;
    private Button moreButton;

    public CustomViewHolder(final View itemView) 
        super(itemView);

        cardName = itemView.findViewById(R.id.cardTitle);
        cardText = itemView.findViewById(R.id.cardText);
        cardFlavor = itemView.findViewById(R.id.cardFlavor);
        cardCost = itemView.findViewById(R.id.dustTextView);
        cardImg = itemView.findViewById(R.id.cardImgView);
        moreButton = itemView.findViewById(R.id.moreButton);

        moreButton.setOnClickListener(new View.OnClickListener() 

            @Override
            public void onClick(View view) 
                Toast.makeText(itemView.getContext(), "Clicked:" + getAdapterPosition(), Toast.LENGTH_SHORT).show();
                intent = new Intent(itemView.getContext(), CardActivity.class);
                extras = intent.getExtras();
                if(extras == null)
                    extras = new Bundle();
                
                    extras.putString(CARD_IMG, cardList.Basic.get(getAdapterPosition()).getImg());
                    extras.putString(CARD_FLAVOR, cardList.Basic.get(getAdapterPosition()).getFlavor());
                    extras.putString(CARD_TEXT, cardList.Basic.get(getAdapterPosition()).getText());
                    extras.putString(CARD_TYPE, cardList.Basic.get(getAdapterPosition()).getType());
                    extras.putString(CARD_ARTIST, cardList.Basic.get(getAdapterPosition()).getArtist());
                    extras.putString(CARD_SET, cardList.Basic.get(getAdapterPosition()).getCardSet());
                    extras.putString(CARD_RARITY, cardList.Basic.get(getAdapterPosition()).getRarity());
                    extras.putString(CARD_NAME, cardList.Basic.get(getAdapterPosition()).getName());
                intent.putExtras(extras);
                itemView.getContext().startActivity(intent);
            
        );

    


完整错误如下:

01-29 12:32:07.961 3030-3030/com.venaseph.hearthlopedia E/AndroidRuntime: 致命异常: main 进程:com.venaseph.hearthlopedia,PID:3030 java.lang.RuntimeException:无法启动活动 ComponentInfocom.venaseph.hearthlopedia/com.venaseph.hearthlopedia.CardActivity:java.lang.IllegalArgumentException:目标不能为空。 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892) 在 android.app.ActivityThread.-wrap11(未知来源:0) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593) 在 android.os.Handler.dispatchMessage(Handler.java:105) 在 android.os.Looper.loop(Looper.java:164) 在 android.app.ActivityThread.main(ActivityThread.java:6541) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) 引起:java.lang.IllegalArgumentException:目标不能为空。 在 com.squareup.picasso.RequestCreator.into(RequestCreator.java:618) 在 com.squareup.picasso.RequestCreator.into(RequestCreator.java:601) 在 com.venaseph.hearthlopedia.CardActivity.getBundleValues(CardActivity.java:41) 在 com.venaseph.hearthlopedia.CardActivity.onCreate(CardActivity.java:33) 在 android.app.Activity.performCreate(Activity.java:6975) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892) 在 android.app.ActivityThread.-wrap11(未知来源:0) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593) 在 android.os.Handler.dispatchMessage(Handler.java:105) 在 android.os.Looper.loop(Looper.java:164) 在 android.app.ActivityThread.main(ActivityThread.java:6541) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

此外,如果我保留所有内容并删除intent.putExtras,它不会崩溃。

【问题讨论】:

请检查您的 xml 文件中是否定义了 R.id.cardImgView 并检查 holder.cardImg 是否不为空。 两者似乎都按预期运行,并且都包含在内而不是 null 您能发布您的 CardActivity 吗?异常发生在 CardActivity.java:41... 【参考方案1】:

那是因为你的intentnull,替换成下面的代码

public void onClick(View view) 
    intent = new Intent(itemView.getContext(), CardActivity.class);
    extras = new Bundle(); //<-- so that bundle wont be null anymore
        extras.putString(CARD_IMG, cardList.Basic.get(getAdapterPosition()).getImg());
        extras.putString(CARD_FLAVOR, cardList.Basic.get(getAdapterPosition()).getFlavor());
        extras.putString(CARD_TEXT, cardList.Basic.get(getAdapterPosition()).getText());
        extras.putString(CARD_TYPE, cardList.Basic.get(getAdapterPosition()).getType());
        extras.putString(CARD_ARTIST, cardList.Basic.get(getAdapterPosition()).getArtist());
        extras.putString(CARD_SET, cardList.Basic.get(getAdapterPosition()).getCardSet());
        extras.putString(CARD_RARITY, cardList.Basic.get(getAdapterPosition()).getRarity());
        extras.putString(CARD_NAME, cardList.Basic.get(getAdapterPosition()).getName());
    intent.putExtras(extras);
    itemView.getContext().startActivity(intent);

【讨论】:

之前尝试过这种方法,但再次确定。仍然得到这个错误和崩溃。 java.lang.RuntimeException:无法启动活动 ComponentInfocom.venaseph.hearthlopedia/com.venaseph.hearthlopedia.CardActivity:java.lang.IllegalArgumentException:目标不能为空。【参考方案2】:

由于bundle 为空,因此Null Pointer Exception

只需实例化 bundle 并添加值。

public void onClick(View view) 
    intent = new Intent(itemView.getContext(), CardActivity.class);
    if(extras == null)
        extras = new Bundle();
    
    extras.putString(CARD_IMG, cardList.Basic.get(getAdapterPosition()).getImg());
    extras.putString(CARD_FLAVOR, cardList.Basic.get(getAdapterPosition()).getFlavor());
    extras.putString(CARD_TEXT, cardList.Basic.get(getAdapterPosition()).getText());
    extras.putString(CARD_TYPE, cardList.Basic.get(getAdapterPosition()).getType());
    extras.putString(CARD_ARTIST, cardList.Basic.get(getAdapterPosition()).getArtist());
    extras.putString(CARD_SET, cardList.Basic.get(getAdapterPosition()).getCardSet());
    extras.putString(CARD_RARITY, cardList.Basic.get(getAdapterPosition()).getRarity());
    extras.putString(CARD_NAME, cardList.Basic.get(getAdapterPosition()).getName());
    intent.putExtras(extras);
    itemView.getContext().startActivity(intent);

【讨论】:

也试过了,还是报错:java.lang.RuntimeException: Unable to start activity ComponentInfocom.venaseph.hearthlopedia/com.venaseph.hearthlopedia.CardActivity: java.lang.IllegalArgumentException : 目标不能为空。 你能分享异常的堆栈跟踪吗...编辑问题并将其放在那里。 添加了全文【参考方案3】:

试试这个编辑

public void onClick(View view) 
    Intent intent = new Intent(itemView.getContext(), CardActivity.class);
    Bundle extras = new Bundle();
    if (extras != null) 
        extras.putString(CARD_IMG, cardList.Basic.get(getAdapterPosition()).getImg());
        extras.putString(CARD_FLAVOR, cardList.Basic.get(getAdapterPosition()).getFlavor());
        extras.putString(CARD_TEXT, cardList.Basic.get(getAdapterPosition()).getText());
        extras.putString(CARD_TYPE, cardList.Basic.get(getAdapterPosition()).getType());
        extras.putString(CARD_ARTIST, cardList.Basic.get(getAdapterPosition()).getArtist());
        extras.putString(CARD_SET, cardList.Basic.get(getAdapterPosition()).getCardSet());
        extras.putString(CARD_RARITY, cardList.Basic.get(getAdapterPosition()).getRarity());
        extras.putString(CARD_NAME, cardList.Basic.get(getAdapterPosition()).getName());
        intent.putExtras(extras);
        itemView.getContext().startActivity(intent);
    

【讨论】:

试过这个,但它从来没有进入条件。 @Venaseph 试试这个 为清楚起见,在原始帖子中添加了完整文件。

以上是关于RecyclerView 中的捆绑问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 Recycler View 将房间数据库滚动到特定位置

Android RecyclerView 绘制流程及Recycler缓存

在水平和垂直的recyclerview中膨胀布局,具有recycler视图的FlexboxLayout添加视图水平自动垂直

滚动 Recycler View 时有意丢失数据

Android RecyclerView 绘制流程及Recycler缓存

访问 Recycler´s Adapter 中的 ViewModel