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

RecyclerView按钮修改MainActivity的TextView报空指针异常求助

问题描述

我是Android开发新手,正在开发一个卡路里计算项目,用RecyclerView展示食物列表。点击RecyclerView中的按钮时,想把列表内对应TextView的数值同步更新到MainActivity的TextView,但执行到mm.kalori.setText(ilkadet);时触发NullPointerException空指针异常。

相关代码

MainActivity

public class MainActivity extends AppCompatActivity {

    public TextView kalori;
    RecyclerView rv;
    List<yiyecek> yiyecekList;

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

        rv=findViewById(R.id.myrecycler);
        kalori=findViewById(R.id.kalori);

        yiyecekList= new ArrayList<>();
        yiyecekList.add(new yiyecek("Egg","50"));
        yiyecekList.add(new yiyecek("Cheese","150"));

        rv.setLayoutManager(new LinearLayoutManager(this));
        rv.setAdapter(new MyAdapter(this,yiyecekList));
    }
}

MyAdapter

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

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

import java.util.List;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    Context context;
    List<yiyecek> yiyecekler;

    public MyAdapter(Context context, List<yiyecek> yiyecekler ) {
        this.context = context;
        this.yiyecekler = yiyecekler;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new MyAdapter.MyViewHolder(LayoutInflater.from(context).inflate(R.layout.yiyecekrowitem,parent,false));
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        yiyecek ymk=yiyecekler.get(position);
        String name=ymk.getAd();
        String kalori=ymk.getKalori();

        holder.text.setText(name);
        holder.textkalori.setText(kalori);
    }

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

    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView text,textkalori,textadet;
        public Button ekle;

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

            textadet=itemView.findViewById(R.id.adet);
            text = itemView.findViewById(R.id.textViewad);
            textkalori = itemView.findViewById(R.id.textViewKalori);
            ekle=itemView.findViewById(R.id.butonekle);

            itemView.findViewById(R.id.butonekle).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String ilkadet=textadet.getText().toString();  
                    MainActivity mm=new MainActivity();
                    mm.kalori.setText(ilkadet);
                }
            });
        }
    }
}

RecyclerView列表项布局(yiyecekrowitem.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="97dp"
    android:layout_margin="8dp"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:id="@+id/textViewad"
        android:layout_width="103dp"
        android:layout_height="48dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="11dp"
        android:layout_marginTop="11dp"
        android:gravity="center"
        android:text="TextView"
        android:textAlignment="center"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/textViewKalori"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="22dp"
        android:layout_marginTop="60dp"
        android:gravity="center"
        android:text="100"
        android:textAlignment="center"
        android:textSize="20sp" />

    <Button
        android:id="@+id/butonekle"
        android:layout_width="150dp"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="284dp"
        android:layout_marginTop="24dp"
        android:text="EKLE" />

    <TextView
        android:id="@+id/adet"
        android:layout_width="70dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="191dp"
        android:layout_marginTop="25dp"
        android:textColor="#282828"
        android:text="0"
        android:textSize="29sp"
        android:textAlignment="center"
        android:gravity="center"/>

</RelativeLayout>

异常日志

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.kalorirecyclerdeneme, PID: 30408
    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
        at com.example.kalorirecyclerdeneme.MyAdapter$MyViewHolder$1.onClick(MyAdapter.java:91)
        at android.view.View.performClick(View.java:7448)
        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1211)
        at android.view.View.performClickInternal(View.java:7425)
        at android.view.View.access$3600(View.java:810)
        at android.view.View$PerformClick.run(View.java:28305)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
I/Process: Sending signal. PID: 30408 SIG: 9

问题原因

空指针的直接原因是你创建了一个新的MainActivity实例MainActivity mm=new MainActivity();,这个新实例并没有经过Android系统的生命周期回调(onCreate没执行),所以mm.kalori变量没有被初始化(还是null),调用setText自然会抛出空指针异常。你需要操作的是当前正在显示的MainActivity实例,而不是新建一个。

解决方法

方法一:接口回调(推荐,低耦合)

通过定义回调接口,让Adapter把点击事件的数据传递给MainActivity,这种方式符合面向对象设计原则,降低耦合度。

  1. 在MyAdapter中定义回调接口
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    Context context;
    List<yiyecek> yiyecekler;
    private OnAddButtonClickListener listener; // 新增回调接口变量

    // 定义回调接口
    public interface OnAddButtonClickListener {
        void onAddClicked(String count);
    }

    // 修改构造方法,传入回调接口实例
    public MyAdapter(Context context, List<yiyecek> yiyecekler, OnAddButtonClickListener listener) {
        this.context = context;
        this.yiyecekler = yiyecekler;
        this.listener = listener;
    }

    // ... 其他原有代码不变

    public class MyViewHolder extends RecyclerView.ViewHolder {
        // ... 其他原有代码不变

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            // ... 其他原有代码不变

            itemView.findViewById(R.id.butonekle).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String ilkadet=textadet.getText().toString();  
                    // 调用回调方法传递数据
                    if (listener != null) {
                        listener.onAddClicked(ilkadet);
                    }
                }
            });
        }
    }
}
  1. MainActivity实现回调接口
public class MainActivity extends AppCompatActivity implements MyAdapter.OnAddButtonClickListener {

    public TextView kalori;
    RecyclerView rv;
    List<yiyecek> yiyecekList;

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

        rv=findViewById(R.id.myrecycler);
        kalori=findViewById(R.id.kalori);

        yiyecekList= new ArrayList<>();
        yiyecekList.add(new yiyecek("Egg","50"));
        yiyecekList.add(new yiyecek("Cheese","150"));

        rv.setLayoutManager(new LinearLayoutManager(this));
        // 创建Adapter时传入this(当前Activity实现了回调接口)
        rv.setAdapter(new MyAdapter(this,yiyecekList, this));
    }

    // 实现回调方法,更新TextView
    @Override
    public void onAddClicked(String count) {
        kalori.setText(count);
    }
}

方法二:直接强转Context(适合新手快速实现,耦合度较高)

如果只是快速验证功能,可以把传入的Context强转为MainActivity实例,直接操作其TextView:

修改MyAdapter的点击事件代码:

itemView.findViewById(R.id.butonekle).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String ilkadet=textadet.getText().toString();  
        // 把Context强转为MainActivity
        MainActivity currentActivity = (MainActivity) context;
        currentActivity.kalori.setText(ilkadet);
    }
});

这种方式简单直接,但会让Adapter和MainActivity产生强耦合,后续扩展或修改Activity时容易出问题,建议优先使用接口回调。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:37:07