Home > Enterprise >  Android Studio Changing Theme and Storing Using SharedPreferences
Android Studio Changing Theme and Storing Using SharedPreferences

Time:10-27

I am trying to implement an option item in my action bar, where the user can select whether they want the app to be light or dark theme, then store that persistently using SharedPreferences and get the same theme they picked once app relaunches.

I first instantiated my SharedPrefs in my Application.kt class: `

class App : Application() {

    init {
        instance = this
    }

    companion object {
        private var instance: Application? = null

        lateinit var room: Postdb
        lateinit var retrofit: Retrofit
        lateinit var sharedPreferences: SharedPreferences


        fun applicationContext() : Context {
            return instance!!.applicationContext
        }
    }

    override fun onCreate() {
        room = Room.databaseBuilder(
            applicationContext,
            Postdb::class.java,
            Postdb.DATABASE_NAME
        ).build()

        retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        sharedPreferences = getSharedPreferences("MySharedPref", MODE_PRIVATE)


        super.onCreate()
    }
}

Then, in MainActivity.kt , I implemented this:

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.mymenu, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {

      var editor =  App.sharedPreferences.edit()

        when(item.itemId){
            R.id.menuRead ->
            {
                Toast.makeText(this,"Pulling data from Room",Toast.LENGTH_SHORT).show()
            }

            R.id.menuDelete ->
            {
                Toast.makeText(this,"Deleting data from Room",Toast.LENGTH_SHORT).show()
                viewModel.deleteData()
            }
            R.id.lightTheme ->
            {
                Toast.makeText(this,"Switching to Light Theme!",Toast.LENGTH_SHORT).show()
                AppCompatDelegate.setDefaultNightMode(light)

                editor.putInt("light", light)
                editor.apply()

            }

            R.id.darkTheme ->
            {
                Toast.makeText(this,"Switching to Dark Theme!",Toast.LENGTH_SHORT).show()
                AppCompatDelegate.setDefaultNightMode(dark)

                editor.putInt("dark", dark)
                editor.apply()

            }

        }
//        editor.commit()

        return true



    }

`

Finally, under onCreate() I implemented this: `

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private val viewModel : MainViewModel by viewModels()
    var light = AppCompatDelegate.MODE_NIGHT_NO
    var dark = AppCompatDelegate.MODE_NIGHT_YES
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val sp : SharedPreferences = App.applicationContext().getSharedPreferences("MySharedPref", MODE_PRIVATE)

         //val theme = sp.getInt("light",dark)
        val theme = sp.getInt("dark",light)

        if(theme == 1){
        AppCompatDelegate.setDefaultNightMode(theme)}
        else{
            AppCompatDelegate.setDefaultNightMode(light)
        }

`

The whole idea is that when the user selects "Dark Theme" option, it is saved via Shared Prefs, and then if app re-launches, it is still in "Dark Theme" as the default option should be just light theme.

Before implementing sharedprefs, I can switch between themes correctly but obviously they did not save. However, after implementing sharedprefs, the I cannot switch themes.

Any help or guidance would be much appreciated!

CodePudding user response:

You're using two different preference keys, "light" and "dark", for the same setting, which doesn't really make sense. Your onCreate() only looks at whatever was put in the "dark" key, but when the user chooses a light theme, you never write to that "dark" key, only the "light" key. This means your code will never detect that the light theme was chosen.

Instead, create a single key. I think it makes sense to call it night mode, since you are storing an int that represents which mode to use. You should always put keys into a constant so you don't have to worry about typos.

// At top level or in some object:
const val KEY_NIGHT_MODE = "nightMode"

// Menu options:
            R.id.lightTheme ->
            {
                Toast.makeText(this,"Switching to Light Theme!",Toast.LENGTH_SHORT).show()
                AppCompatDelegate.setDefaultNightMode(light)

                editor.putInt(KEY_NIGHT_MODE, light)
                editor.apply()

            }

            R.id.darkTheme ->
            {
                Toast.makeText(this,"Switching to Dark Theme!",Toast.LENGTH_SHORT).show()
                AppCompatDelegate.setDefaultNightMode(dark)

                editor.putInt(KEY_NIGHT_MODE, dark)
                editor.apply()

            }

// Reading and applying the value in onCreate (no if/else needed):
val theme = sp.getInt(KEY_NIGHT_MODE, light)
AppCompatDelegate.setDefaultNightMode(theme)

I should also point out a couple of code smells I see:

These light and dark properties are redundant. You should use the constants directly where they are needed. Also, the fact that these are mutable properties is very weird. You would never have a reason to change them, so it is just inviting possible bugs that you don't need to.

    var light = AppCompatDelegate.MODE_NIGHT_NO
    var dark = AppCompatDelegate.MODE_NIGHT_YES

In this code you explicitly get a SharedPreferences that is the same as the one already defined in your Application's companion object. That's redundant and error prone.

val sp : SharedPreferences = App.applicationContext().getSharedPreferences("MySharedPref", MODE_PRIVATE)

I'd replace it with, since that's what you're already using in your onOptionsItemSelected():

val sp = App.sharedPreferences
  • Related