androidkotlinandroid-fragmentssharedpreferencespreferencefragment

My application force closed when trying to replace fragment to preference fragment in kotlin Android


So my app has a bottom navigation where one of the page is the settings page. In the settings fragment, I inherited from PreferenceFragment. Here is the code for the SettingsFragment class:

class SettingsFragment : PreferenceFragmentCompat() {
private lateinit var binding: FragmentSettingsBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

}

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    binding = FragmentSettingsBinding.inflate(inflater,container,false)
    return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

}

override fun onCreatePreferences(bundle: Bundle?, s: String?) {
    addPreferencesFromResource(R.xml.preferences)
}

}

Here is the main activity where the transaction happens:

class MainActivity : AppCompatActivity(){

private lateinit var binding: ActivityMainBinding

//Make it a global variable
private val homeFragment = HomeFragment()
private val profileFragment = ProfileFragment()
private val favoriteFragment = FavoriteFragment()
private val settingsFragment = SettingsFragment()

companion object {
    private val TAG = MainActivity::class.java.simpleName
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)


    replaceFragment(homeFragment)
    binding.bottomNavigation.setOnNavigationItemSelectedListener {
        when(it.itemId){
            R.id.ic_home -> replaceFragment(homeFragment)
            R.id.ic_profile -> replaceFragment(profileFragment)
            R.id.ic_favorite -> replaceFragment(favoriteFragment)
            R.id.ic_settings -> replaceFragment(settingsFragment)
        }
        true
    }
}

private fun replaceFragment(fragment: Fragment){
    if (fragment!=null){
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.fragment_container,fragment)
        transaction.commit()
    }
}

}

Here is also the log:

2021-04-15 11:42:42.566 20177-20177/com.dicoding.githubclone E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dicoding.githubclone, PID: 20177
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setAdapter(androidx.recyclerview.widget.RecyclerView$Adapter)' on a null object reference
    at androidx.preference.PreferenceFragmentCompat.bindPreferences(PreferenceFragmentCompat.java:483)
    at androidx.preference.PreferenceFragmentCompat.onViewCreated(PreferenceFragmentCompat.java:272)
    at com.dicoding.githubclone.fragment.SettingsFragment.onViewCreated(SettingsFragment.kt:36)
    at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:332)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
    at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
    at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:447)
    at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2169)
    at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1992)
    at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
    at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
    at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:239)
    at android.app.ActivityThread.main(ActivityThread.java:8107)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:626)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1015)

I'm not sure how to fix this. Can anyone help me?


Solution

  • As PreferenceFragmentCompat creates it's own recycler view , so don't use onCreateView. Like:

        class SettingsFragment : PreferenceFragmentCompat() {
       // private lateinit var binding: FragmentSettingsBinding
    
    /*    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
        }
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            binding = FragmentSettingsBinding.inflate(inflater,container,false)
            return binding.root
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
        }*/
    
        override fun onCreatePreferences(bundle: Bundle?, s: String?) {
            addPreferencesFromResource(R.xml.preferences)
        }
    }