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,这种方式符合面向对象设计原则,降低耦合度。
- 在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); } } }); } } }
- 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
相关产品推荐
相关产品推荐

