Search code examples
android-studiokotlinfragmentsharedpreferences

Сan't get data from another fragment via sharedPreferences


//FIRST FRAGMENT

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()
    }
}

//SECOND FRAGMENT

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()
    }
}

When I enter data on a fragment in EditText with a first and last name and click the save button, then the data should be saved in SharedPreferences, and then on the previous fragment this data should be displayed in TextView

But no matter how much I try to get this data, the default data remains. I also tried to get this data in onResume and onStart, but everything remained the same


Solution

  • The problem is here:

    class StaffDataFragment : Fragment() {
        val sharedPreferences = activity?.getSharedPreferences("myPrefs", Context.MODE_PRIVATE)
    

    You're using a null-safe ?. call on a null activity, so sharedPreferences is null and you can't use it.

    ?. means you maybe want something to happen. If you find yourself having to use ?. to do something that definitely should always happen, then you need to step back and consider what you are doing wrong. In this case, it's that you're trying to get something from the activity when it isn't available yet.

    SharedPreferences has no good reason to be nullable at the time you're using it, so you should not be putting it in a nullable property.

    You can't get something that relies on the Activity as a property declaration, because the fragment isn't attached to an activity yet when the Fragment is still being instantiated. You should move this line of code inside onViewCreated() and change all the ?. into .. You can replace activity with requireActivity() so it won't be nullable. requireActivity() is safe to call inside functions that fall within the fragment's view lifecycle.