0

I have two activities Main and Settings, So in settings activity, in onDestroy()

override fun onDestroy() {
    super.onDestroy()
    Log.d("Activity Lifecycle", "onDestroy invoked")
    val editor:SharedPreferences.Editor =  sharedPreferences!!.edit()
    editor.putInt(getString(R.string.SOME_VALUE), this.somevalue!!)
    editor.apply()
    editor.commit()
    Log.d("Editor", "values commited")
    setResult(1) // for onActivityResult
}

and in main activity:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    Log.d("onActivityResult", "called")
    val somevalue = sharedPreferences!!.getInt(getString(R.string.SOME_VALUE),0)
    times_2.text = somevalue.toString()
}

and also this in main activity:

override fun onResume() {
    super.onResume()
    Log.d("Activity Lifecycle", "onResume invoked")
    val somevalue = sharedPreferences!!.getInt(getString(R.string.SOME_VALUE),0)
    times_2.text = somevalue.toString()
}

so the thing is onActivityResult is called first, then onResume, and then the editor values are commited. I want to refresh parent activity with the updated values

Akshit W.
  • 79
  • 10
  • 1
    Hi @Akshit the `editor.apply()` is async function to commit changes to shared preference, try removing that, try keeping only `editor.commit()` and make sure `finish()`/`onBackPressed` function is called when you done computing you work. – Chetan Gupta Jun 27 '20 at 06:31
  • 1
    @ChetanGarg That's incorrect. `apply()` and `commit()` are both synchronous, but `commit()` involves a file operation, so should be avoided. `apply()` immediately changes the singleton value and also fires off an asynchronous `commit()` call. @AkshitW, move your code to `onStop()` or `onPause()` and remove the `commit()` call. And use appropriate nullability. Frequent use of `!!` is a code smell. – Tenfour04 Jun 27 '20 at 16:05
  • 1
    Hi @Tenfour04 please look at this link https://stackoverflow.com/questions/5960678/whats-the-difference-between-commit-and-apply-in-sharedpreferences, first comment have 111+ upvotes and it says what I say. – Chetan Gupta Jun 27 '20 at 17:24
  • 2
    @ChetanGarg That comment says what I said, not what you said. You have them swapped. And both methods return synchronously, and the results can be trusted immediately. `apply()` *additionally* does an asynchronous operation to write to disk. – Tenfour04 Jun 27 '20 at 17:36
  • 1
    @Tenfour04 my mistake I wrote it down wrong I also meant the same in terms of DB writing is async – Chetan Gupta Jun 29 '20 at 08:19

1 Answers1

1

Please do not have any kind of IO operation in onDestroy. You can make use of onStop in this case. Also make sure the super constructor gets invoked after you are done with the saving task.

override fun onStop() {
    
    // Do save activity
    val editor:SharedPreferences.Editor =  sharedPreferences!!.edit()
    editor.putInt(getString(R.string.SOME_VALUE), this.somevalue!!)
    // editor.apply() // Use this when you want this operation to be async
    editor.commit() // Non async save
    setResult(1) // for onActivityResult

    // Once save is done, call super method to proceed with stop
    super.onStop() // Always call after operation
}

Also it is good practice to use .apply() when you have more number of key value pairs.

Sumit Sahoo
  • 2,949
  • 1
  • 25
  • 37
  • 1
    `commit()`should not be called from the main thread. The order of calling `super.onStop()` doesn’t matter here because this method is called on the same thread (main) that will call `onActivityResult()` on the other Activity. – Tenfour04 Jun 29 '20 at 12:07
  • 1
    The order does matter, for example consider a situation when `onDestroy` is invoked and by the time the calculation (or any save process) is completed the activity is destroyed and hence any reference that is tied to activity lifecycle gets destroyed as well. Hence sometimes the sequence of execution does matter. And yes `commit()` should not be called from main thread as it's basically an IO operation but given a scenario when it's required makes sense without overcomplicating things and for other usecase `apply()` is always preferred. – Sumit Sahoo Jun 29 '20 at 12:32
  • 1
    I said it doesn't matter *in this case*. `commit()` is synchronous. `onStop()` runs on the main thread and so does `onActivityResult()`, so everything you're doing above will be done by the time `onStop()` returns, which is before `onActivityResult()` is called on the same thread. – Tenfour04 Jun 29 '20 at 13:03
  • 1
    `apply()` should be used here too. The only reason to ever use `commit()` is when you need to guarantee that the file write has successfully completed before continuing, which you aren't even checking above. When you get a value from SharedPreferences, it uses the in-memory cache, so `apply()` is perfectly adequate and instantaneous. – Tenfour04 Jun 29 '20 at 13:03