You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android RecyclerView加载列表时TextView.setText空指针异常排查

问题背景

正在开发加密货币价格提醒应用,核心功能为:当用户选定的加密货币价格进入预设预算区间时,向用户发送买入提醒。应用主Activity需要展示通过API拉取的全量加密货币列表,采用RecyclerView实现该列表功能,目前已完成Adapter适配器、CryptoCurrency数据模型类、列表项布局文件的编写,传入测试数据验证列表展示效果时程序崩溃。

异常信息
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
相关实现代码

MainActivity.java

package com.example.pricepointcrypto;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    CryptoCurrencyAdapter cryptoCurrencyAdapter;
    ArrayList<CryptoCurrency> cryptoCurrencies = new ArrayList<>();

    private String[] currencyNames = {"Bitcoin (BTC)", "Ethereal (ETH)"};
    private String[] currencyRates = {"20509.88 USD" , "1174.3 USD"};
    private String[] mktCap = {"3440.0%", "3235.5765%"};
    private String[] totalCoins = {"3345444", "3215434"};
    private String[] tradedVolume = {"4534B", "98978B"};

    private int[] currencyLogos = {R.drawable.cryptocurrencylogo, R.drawable.ic_launcher_background};

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

        for(int i=0;i<currencyNames.length;i++)
        {
            CryptoCurrency cryptoCurrency = new CryptoCurrency();

            cryptoCurrency.setCurrencyName(currencyNames[i]);
            cryptoCurrency.setCurrentRate(currencyRates[i]);
            cryptoCurrency.setMarketCap(mktCap[i]);
            cryptoCurrency.setTotalCoins(totalCoins[i]);
            cryptoCurrency.setTradedVolume(tradedVolume[i]);

            cryptoCurrency.setCurrencyLogo(currencyLogos[i]);

            cryptoCurrencies.add(cryptoCurrency);
        }


        cryptoCurrencyAdapter = new CryptoCurrencyAdapter(cryptoCurrencies);

        recyclerView = (RecyclerView)findViewById(R.id.crypto_currencies);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(cryptoCurrencyAdapter);

    }
}

CryptoCurrency.java

package com.example.pricepointcrypto;

public class CryptoCurrency {

    private String currencyName;
    private String currentRate;
    private String marketCap;
    private String totalCoins;
    private String tradedVolume;

    private int currencyLogo;

    public int getCurrencyLogo() {
       return currencyLogo;
    }

    public void setCurrencyLogo(int currencyLogo) {
        this.currencyLogo = currencyLogo;
    }

    public String getCurrencyName() {
        return currencyName;
    }

    public void setCurrencyName(String currencyName) {
        this.currencyName = currencyName;
    }

    public String getCurrentRate() {
        return currentRate;
    }

    public void setCurrentRate(String currentRate) {
        this.currentRate = currentRate;
    }

    public String getMarketCap() {
        return marketCap;
    }

    public void setMarketCap(String marketCap) {
        this.marketCap = marketCap;
    }

    public String getTotalCoins() {
        return totalCoins;
    }

    public void setTotalCoins(String totalCoins) {
        this.totalCoins = totalCoins;
    }

    public String getTradedVolume() {
        return tradedVolume;
    }

    public void setTradedVolume(String tradedVolume) {
        this.tradedVolume = tradedVolume;
    }
}

CryptoCurrencyAdapter.java

package com.example.pricepointcrypto;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class CryptoCurrencyAdapter extends RecyclerView.Adapter<CryptoCurrencyAdapter.ViewHolder> {

    List<CryptoCurrency> cryptoCurrencyList;
    Context context;

    public CryptoCurrencyAdapter(List<CryptoCurrency> cryptoCurrencyList) {
        this.cryptoCurrencyList = cryptoCurrencyList;
    }

    @NonNull
    @Override
    public CryptoCurrencyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.crypto_card_layout, parent,false);
        ViewHolder viewHolder = new ViewHolder(view);
        context = parent.getContext();
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull CryptoCurrencyAdapter.ViewHolder holder, int position) {
        CryptoCurrency cryptoCurrency = cryptoCurrencyList.get(position);

        holder.currencyName.setText(cryptoCurrency.getCurrencyName());
        holder.currentRate.setText(cryptoCurrency.getCurrentRate());
        holder.marketCap.setText(cryptoCurrency.getMarketCap());
        holder.totalCoins.setText(cryptoCurrency.getTotalCoins());
        holder.tradedVolume.setText(cryptoCurrency.getTradedVolume());

        holder.currencyImg.setImageResource(cryptoCurrency.getCurrencyLogo());

        holder.currencyCard.setOnClickListener(view -> Toast.makeText(context,"The position is:"+position,Toast.LENGTH_SHORT).show());

    }

    @Override
    public int getItemCount() {
        return cryptoCurrencyList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        ImageView currencyImg;

        TextView currencyName;
        TextView currentRate;
        TextView marketCap;
        TextView totalCoins;
        TextView tradedVolume;

        CardView currencyCard;


        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            currencyImg = itemView.findViewById(R.id.currency_logo);

            currencyName = itemView.findViewById(R.id.currency_name);
            currentRate = itemView.findViewById(R.id.current_rate);
            marketCap = itemView.findViewById(R.id.market_cap);
            totalCoins = itemView.findViewById(R.id.coin_total);
            tradedVolume = itemView.findViewById(R.id.traded_volume);

            currencyCard = itemView.findViewById(R.id.currency_card);
        }
    }
}
异常触发原因

空指针的直接触发点是onBindViewHolder执行时,持有的某个TextView/ImageView实例为null,根本原因是资源ID匹配失败:ViewHolder初始化时调用findViewById传入的R.id.xxx,在加载的crypto_card_layout布局中找不到对应控件,方法直接返回null,后续调用null对象的setText/setImageResource方法就会崩溃。
常见的触发场景:

  • 列表项布局中控件的android:id拼写错误,比如把currency_name多写字母、大小写写错
  • 布局中漏写了对应控件的ID属性
  • onCreateViewHolder加载布局时传错了资源ID,误加载了其他不含对应控件的布局

注:当前MainActivity的测试数据组装、RecyclerView配置,以及CryptoCurrency数据模型的代码均无逻辑问题,不需要修改。

修复方案
  1. 打开res/layout/crypto_card_layout.xml列表项布局文件,逐行核对所有控件的ID,和ViewHolder中绑定的ID一一对应:
    • 加密货币logo ImageView 对应ID:currency_logo
    • 货币名称TextView 对应ID:currency_name
    • 当前价格TextView 对应ID:current_rate
    • 市值TextView 对应ID:market_cap
    • 总发行量TextView 对应ID:coin_total
    • 交易量TextView 对应ID:traded_volume
    • 外层卡片CardView 对应ID:currency_card
  2. 给缺失ID的控件补上对应@+id/xxx属性,把写错的ID改成和代码中完全一致的命名。
  3. 核对onCreateViewHolder中inflate的布局资源是R.layout.crypto_card_layout,不要误引用其他布局。
  4. 修改完成后在Android Studio顶部菜单栏执行Build -> Clean Project,清除资源缓存后重新运行即可。

可参考的正确列表项布局示例:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/currency_card"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    app:cardCornerRadius="8dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="12dp">

        <ImageView
            android:id="@+id/currency_logo"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:contentDescription="currency logo"/>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_marginStart="12dp"
            android:orientation="vertical">

            <TextView
                android:id="@+id/currency_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16sp"
                android:textStyle="bold"/>

            <TextView
                android:id="@+id/current_rate"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="4dp"
                android:textSize="14sp"/>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="4dp">
                <TextView
                    android:id="@+id/market_cap"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:textSize="12sp"/>
                <TextView
                    android:id="@+id/coin_total"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:textSize="12sp"/>
                <TextView
                    android:id="@+id/traded_volume"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:textSize="12sp"/>
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</androidx.cardview.widget.CardView>

内容的提问来源于stack exchange,提问作者Sarimm Chaudhry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 18:31:23