You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 16:35:40