无法通过SharedPreferences在Fragment间获取数据的问题
问题描述
在StaffDataFragment的EditText中输入姓名并点击保存按钮后,预期数据会被保存到SharedPreferences中,返回StaffProfileFragment时,TextView应显示新保存的数据。但实际始终显示默认值,即使尝试在onResume、onStart生命周期方法中获取数据,问题依然存在。
相关代码
第一个Fragment:StaffProfileFragment
class StaffProfileFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_staff_profile, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val staffName = view.findViewById<TextView>(R.id.staffName) val staffSurname = view.findViewById<TextView>(R.id.staffSurname) val sharedPreferences = activity?.getSharedPreferences("myPrefs", Context.MODE_PRIVATE) staffName?.text = sharedPreferences?.getString("StaffName", "Имя") staffSurname?.text = sharedPreferences?.getString("StaffSurname", "Фамилия") val exitButton = view.findViewById<Button>(R.id.exitButton) exitButton.setOnClickListener { FirebaseAuth.getInstance().signOut() parentFragmentManager?.beginTransaction() ?.replace(R.id.club_placeholder, ProfileFragment.newInstance()) ?.addToBackStack(null)?.commit() } val goToStaffData = view.findViewById<ConstraintLayout>(R.id.goToStaffData) goToStaffData.setOnClickListener { parentFragmentManager?.beginTransaction() ?.replace(R.id.club_placeholder, StaffDataFragment.newInstance()) ?.addToBackStack(null)?.commit() } val groupWorkouts = view.findViewById<ConstraintLayout>(R.id.groupWorkouts) groupWorkouts.setOnClickListener { parentFragmentManager?.beginTransaction() ?.replace(R.id.club_placeholder, CreateWorkoutsFragment.newInstance()) ?.addToBackStack(null)?.commit() } val goToChangePassword = view.findViewById<ConstraintLayout>(R.id.goToChangePassword) goToChangePassword.setOnClickListener{ parentFragmentManager?.beginTransaction() ?.replace(R.id.club_placeholder, ChangePasswordFragment.newInstance()) ?.addToBackStack(null)?.commit() } } companion object { fun newInstance() = StaffProfileFragment() } }
第二个Fragment:StaffDataFragment
class StaffDataFragment : Fragment() { val sharedPreferences = activity?.getSharedPreferences("myPrefs", Context.MODE_PRIVATE) override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_staff_data, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val switch: Switch = view.findViewById(R.id.staffDataSwtcher) val editTextName: EditText = view.findViewById(R.id.editTextStaffName) val editTextSurname: EditText = view.findViewById(R.id.editTextStaffSurname) val backButton: TextView = view.findViewById(R.id.staffDataBackButton) editTextName.isEnabled = false editTextSurname.isEnabled = false backButton.setOnClickListener{ parentFragmentManager?.beginTransaction() ?.replace(R.id.club_placeholder, StaffProfileFragment.newInstance()) ?.commit() } switch.setOnCheckedChangeListener { _, isChecked -> if (isChecked) { // 如果Switch开启,让EditText可输入 editTextName.isEnabled = true editTextSurname.isEnabled = true } else { // 如果Switch关闭,让EditText不可输入 editTextName.isEnabled = false editTextSurname.isEnabled = false } } val saveButton: Button = view.findViewById(R.id.saveStaffDataName) saveButton.setOnClickListener { val name = editTextName.text.toString() val surname = editTextSurname.text.toString() val editor = sharedPreferences?.edit() editor?.putString("StaffName", name) editor?.putString("StaffSurname", surname) editor?.apply() switch.isChecked = false editTextName.isEnabled = false editTextSurname.isEnabled = false } } companion object { fun newInstance() = StaffDataFragment() } }
问题分析与解决
核心问题1:SharedPreferences获取时机错误
StaffDataFragment中把sharedPreferences声明为类成员变量并直接初始化,此时Fragment还未与Activity关联,activity为null,导致sharedPreferences始终是null,点击保存时根本没有执行写入操作。
核心问题2:返回Fragment时创建新实例
点击返回按钮时,用replace创建了新的StaffProfileFragment实例,即使数据保存成功,新实例初始化时可能还没读到最新数据,而且也不符合返回栈的预期行为。
修复方案
1. 修正SharedPreferences获取时机
删除StaffDataFragment中的类成员sharedPreferences,在保存按钮的点击事件中临时获取:
saveButton.setOnClickListener { val name = editTextName.text.toString() val surname = editTextSurname.text.toString() // 在这里获取SharedPreferences,此时Activity已关联 val sharedPreferences = activity?.getSharedPreferences("myPrefs", Context.MODE_PRIVATE) val editor = sharedPreferences?.edit() editor?.putString("StaffName", name) editor?.putString("StaffSurname", surname) editor?.apply() switch.isChecked = false editTextName.isEnabled = false editTextSurname.isEnabled = false }
2. 优化返回逻辑,复用原有Fragment实例
修改StaffDataFragment中返回按钮的点击事件,用popBackStack()回到返回栈中的原有StaffProfileFragment实例:
backButton.setOnClickListener{ parentFragmentManager?.popBackStack() }
3. 在StaffProfileFragment中添加数据刷新逻辑
将数据读取逻辑抽成独立方法,在onResume中调用,确保回到前台时刷新最新数据:
class StaffProfileFragment : Fragment() { private lateinit var staffName: TextView private lateinit var staffSurname: TextView override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_staff_profile, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) staffName = view.findViewById(R.id.staffName) staffSurname = view.findViewById(R.id.staffSurname) // 初始化时加载数据 refreshProfileData() // 其他按钮点击逻辑保持不变... } override fun onResume() { super.onResume() // 回到前台时刷新数据 refreshProfileData() } private fun refreshProfileData() { val sharedPreferences = activity?.getSharedPreferences("myPrefs", Context.MODE_PRIVATE) staffName.text = sharedPreferences?.getString("StaffName", "Имя") staffSurname.text = sharedPreferences?.getString("StaffSurname", "Фамилия") } companion object { fun newInstance() = StaffProfileFragment() } }
完成以上修改后,数据就能正常保存并在返回时显示最新值了。
内容的提问来源于stack exchange,提问作者DANILA BYKHOVOY
相关产品推荐
相关产品推荐

