如何在MainActivity.java中修改fragment_profile对应页面的TextView文本
问题原因
- 你使用的是Navigation导航组件,所有子Fragment都托管在
R.id.nav_host_fragment容器中,Activity直接调用findFragmentById(R.id.fragment_profile)无法获取到对应Fragment实例,会返回空对象,后续操作自然报错。 - 你在Activity的
onCreate生命周期就调用了updateUI(null),此时Profile Fragment还未完成初始化创建,即使能拿到实例也找不到其内部的View控件。
推荐解决方案
方案1:共享ViewModel(官方推荐,耦合度最低)
这是Android官方推荐的Activity和Fragment通信方案,不存在生命周期兼容问题。
- 首先创建共享ViewModel类
public class UserViewModel extends ViewModel { private final MutableLiveData<String> profileTitle = new MutableLiveData<>("Login"); public LiveData<String> getProfileTitle() { return profileTitle; } public void setProfileTitle(String title) { profileTitle.setValue(title); } }
- 修改MainActivity的
updateUI方法,仅修改ViewModel数据,不直接操作Fragment控件
private void updateUI(FirebaseUser user) { UserViewModel viewModel = new ViewModelProvider(this).get(UserViewModel.class); if (user != null) { viewModel.setProfileTitle("Profile"); } else { viewModel.setProfileTitle("Login"); } }
- 在ProfileFragment中监听ViewModel数据变化,自行修改文本
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_profile, container, false); TextView titleProfile = view.findViewById(R.id.titleProfile); // 获取和宿主Activity共有的ViewModel实例 UserViewModel viewModel = new ViewModelProvider(requireActivity()).get(UserViewModel.class); // 监听标题变化自动更新文本 viewModel.getProfileTitle().observe(getViewLifecycleOwner(), title -> { titleProfile.setText(title); }); return view; }
方案2:FragmentResultListener(轻量场景使用)
如果不需要持久化状态,只是单次通知可以用这个方案:
- 修改MainActivity的
updateUI方法
private void updateUI(FirebaseUser user) { String targetTitle = user != null ? "Profile" : "Login"; getSupportFragmentManager().setFragmentResult("updateProfileTitle", new Bundle().putString("title", targetTitle)); }
- 在ProfileFragment中监听通知
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_profile, container, false); TextView titleProfile = view.findViewById(R.id.titleProfile); getParentFragmentManager().setFragmentResultListener("updateProfileTitle", getViewLifecycleOwner(), (requestKey, result) -> { titleProfile.setText(result.getString("title")); }); return view; }
注意事项
不要尝试在Activity中直接获取Fragment实例操作其控件,Navigation组件下Fragment会频繁销毁重建,这种写法很容易出现空指针、内存泄漏问题,可维护性极差。
内容的提问来源于stack exchange,提问作者Oleh Prukhnytskyi
相关产品推荐
相关产品推荐

