Android Activity向ViewPager2内Fragment传值报空指针异常
问题根因
崩溃触发的核心原因是传参目标错误,具体逻辑问题如下:
- 你在SecondActivity中先为ViewPager2设置了适配器,适配器的
createFragment回调会自行创建一个全新的ProfileFragment实例加载到页面,这个实例从创建开始就没有被设置过任何arguments参数 - 后续你手动new的
ProfileFragment是完全独立的另一个对象,从未被添加到页面视图栈中,你给这个无用实例调用setArguments不会对实际显示的Fragment产生任何影响 - 页面上真正展示的是适配器创建的无参数Fragment实例,调用
getArguments()会返回null,直接在null对象上调用getString方法就会抛出你遇到的空指针异常。
修复方案
按照以下步骤修改代码即可解决问题:
- 删除SecondActivity中手动创建ProfileFragment实例、给该实例setArguments的无效代码
- 将Intent中获取到的Bundle参数通过构造方法传给ViewPager2的适配器
- 在适配器的
createFragment回调中,给真正要加载的ProfileFragment实例设置arguments参数 - 在ProfileFragment中获取参数前增加空判断,避免极端场景崩溃
- 补充TabLayout与ViewPager2的绑定逻辑,否则Tab点击切换功能无法正常工作
修改后的SecondActivity代码
public class SecondActivity extends AppCompatActivity { private TabLayout tabLayout; private ViewPager2 viewPager2; private Bundle loginBundle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); tabLayout = findViewById(R.id.tablayout); viewPager2 = findViewById(R.id.viewpager2); // 提前取出Intent携带的参数 loginBundle = getIntent().getExtras(); // 初始化适配器时传入参数 viewPager2.setAdapter(createAdapter()); // 绑定TabLayout和ViewPager2,实现Tab切换联动 new TabLayoutMediator(tabLayout, viewPager2, (tab, position) -> { // 按实际需求设置Tab标题,示例为第一个Tab设置"个人资料"标题 if (position == 0) { tab.setText("个人资料"); } }).attach(); } private VpAdapter createAdapter(){ return new VpAdapter(this, loginBundle); } }
修改后的VpAdapter代码
class VpAdapter extends FragmentStateAdapter { private final Bundle fragmentArgs; private static final int NUM_ITEMS = 1; // 构造方法接收需要传递给Fragment的参数 public VpAdapter(FragmentActivity fa, Bundle args){ super(fa); this.fragmentArgs = args; } @Override public Fragment createFragment(int position){ Fragment fragment = null; switch(position){ case 0: fragment = new ProfileFragment(); // 给实际要加载的Fragment设置参数 if (fragmentArgs != null) { fragment.setArguments(fragmentArgs); } break; } return fragment; } @Override public int getItemCount() { return NUM_ITEMS; } }
修改后的ProfileFragment参数获取逻辑
只需要替换onCreateView中取参数、赋值的部分代码即可:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_profile, container, false); welcome = v.findViewById(R.id.welcome); name = v.findViewById(R.id.user_name); age = v.findViewById(R.id.age); description = v.findViewById(R.id.description); occupation = v.findViewById(R.id.occupation); // 先获取arguments,做空判断 Bundle args = getArguments(); if (args != null) { String mStringDate = args.getString("date"); String mStringName = args.getString("name"); String mStringEmail = args.getString("email"); String mStringUserName = args.getString("userName"); String mStringDescription = args.getString("description"); String mStringOccupation = args.getString("occupation"); int mUserAge = args.getInt("age"); // 参数非空时再给控件赋值 welcome.setText("Welcome " + mStringUserName); name.append(mStringUserName); age.append(String.valueOf(mUserAge)); description.append(mStringDescription); occupation.append(mStringOccupation); } return v; }
注意事项
- 不要手动创建
FragmentStateAdapter/ViewPager2管理的Fragment实例,这类Fragment的生命周期完全由适配器接管,手动创建的实例不会被加载到视图中,所有针对手动实例的操作都不会生效 - Fragment中通过
getArguments()获取参数时必须做非空判断,避免参数丢失、传递错误时触发崩溃 - 使用TabLayout配合ViewPager2时,必须通过
TabLayoutMediator做绑定,否则Tab点击、滑动联动功能无法正常工作
内容的提问来源于stack exchange,提问作者Calas
相关产品推荐
相关产品推荐

