Adapter中点击RLAYOUT触发Fragment跳转时AppCompatActivity致应用崩溃
RecyclerView点击跳转Fragment崩溃排查与解决
问题描述
在FirestoreRecyclerAdapter中给RelativeLayout设置点击事件,点击时从Home Fragment切换到Perfil Fragment(注:用户描述中提到的是DescDenuncia Fragment,代码中实际为Perfil),传递Model中的多个参数,但每次点击都会导致应用崩溃。已确认model.getEmpresa等参数本身无问题,怀疑Fragment事务逻辑存在错误。
崩溃代码
package com.example.safe; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import com.firebase.ui.firestore.FirestoreRecyclerAdapter; import com.firebase.ui.firestore.FirestoreRecyclerOptions; //Vinculando o reclycler view ao firestore public class Adapter extends FirestoreRecyclerAdapter<Modelo, Adapter.myviewholder> { public Adapter(@NonNull FirestoreRecyclerOptions<Modelo> options) { super(options); } //Sobrescrevendo o método @Override protected void onBindViewHolder(@NonNull myviewholder holder, int position, @NonNull final Modelo model) { //Associando os itens do atalho ocorrências holder.IDText.setText(model.getID()); holder.tipoText.setText(model.getTipo()); Glide.with(holder.img1.getContext()).load(model.getImg()).into(holder.img1); ///////////////////////////////////////THE PROBLEM IS HERE/////////////////////////////////////////// holder.RLAYOUT.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { AppCompatActivity activity = (AppCompatActivity) view.getContext(); activity.getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, new Perfil( model.getEmpresa(), model.getArea(), model.getSetor(), model.getTipo(), model.getRisco(), model.getImg(), model.getData(), model.getPrazo(), model.getDesc(), model.getResolucao(), model.getID() )).addToBackStack(null).commit(); } }); ////////////////////////////////////////////////////////////////////////////////////////////////////// } @NonNull @Override public myviewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.modelo_atalho_ocorrencias, parent, false); return new myviewholder(view); } //Coneção do reclycler view com essa classe public class myviewholder extends RecyclerView.ViewHolder { //Variáveis do modelo atalho TextView tipoText, IDText; RelativeLayout RLAYOUT; ImageView img1; //Associando os objetos ao modelo atalho public myviewholder(@NonNull View itemView) { super(itemView); tipoText = itemView.findViewById(R.id.txtTipo); img1 = itemView.findViewById(R.id.imageView); IDText = itemView.findViewById(R.id.txtModeloID); RLAYOUT = itemView.findViewById(R.id.RLlayout); } } }
解决方案
1. 修复上下文强转问题
直接将view.getContext()强转为AppCompatActivity存在风险,如果当前上下文是Fragment(而非Activity),会抛出ClassCastException。添加类型判断确保安全:
holder.RLAYOUT.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Context context = view.getContext(); if (!(context instanceof AppCompatActivity)) { Toast.makeText(context, "跳转失败:无效上下文", Toast.LENGTH_SHORT).show(); return; } AppCompatActivity activity = (AppCompatActivity) context; // 后续事务代码 } });
2. 使用Bundle传递Fragment参数(推荐)
Android不推荐通过构造函数给Fragment传参,Fragment重建时会丢失参数并可能引发异常。改用静态newInstance方法+Bundle传递:
第一步:修改Perfil Fragment
public class Perfil extends Fragment { // 静态方法创建Fragment实例并传递参数 public static Perfil newInstance(String empresa, String area, String setor, String tipo, String risco, String img, String data, String prazo, String desc, String resolucao, String id) { Perfil fragment = new Perfil(); Bundle args = new Bundle(); args.putString("empresa", empresa); args.putString("area", area); args.putString("setor", setor); args.putString("tipo", tipo); args.putString("risco", risco); args.putString("img", img); args.putString("data", data); args.putString("prazo", prazo); args.putString("desc", desc); args.putString("resolucao", resolucao); args.putString("id", id); fragment.setArguments(args); return fragment; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 从Bundle中取出参数 if (getArguments() != null) { String empresa = getArguments().getString("empresa"); String area = getArguments().getString("area"); // 其他参数同理取出 } } // 其他Fragment逻辑... }
第二步:修改Adapter中的跳转代码
holder.RLAYOUT.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Context context = view.getContext(); if (!(context instanceof AppCompatActivity)) { Toast.makeText(context, "跳转失败:无效上下文", Toast.LENGTH_SHORT).show(); return; } AppCompatActivity activity = (AppCompatActivity) context; // 使用newInstance创建Fragment Perfil perfilFragment = Perfil.newInstance( model.getEmpresa(), model.getArea(), model.getSetor(), model.getTipo(), model.getRisco(), model.getImg(), model.getData(), model.getPrazo(), model.getDesc(), model.getResolucao(), model.getID() ); // 执行Fragment事务 activity.getSupportFragmentManager() .beginTransaction() .replace(R.id.frameLayout, perfilFragment) .addToBackStack(null) .commit(); } });
3. 验证容器ID正确性
确认R.id.frameLayout确实存在于当前Activity的布局文件中,且是专门用于承载Fragment的容器(比如FrameLayout)。ID错误会导致replace操作失败崩溃。
4. 查看崩溃日志定位根源
打开Logcat,找到崩溃时的异常信息:
- 如果是
ClassCastException:对应上下文强转问题; - 如果是
IllegalStateException:可能是Activity处于不可操作状态(比如正在销毁)时执行事务; - 如果是
NullPointerException:检查Bundle参数读取或Fragment容器是否为空。
内容的提问来源于stack exchange,提问作者Rodrigo
相关产品推荐
相关产品推荐

