I experienced interesting behavior with Handler(Looper.getMainLooper()). It gets executed twice if my app theme (day/night) is set to different from OS Settings. For example if Dark mode is turned off in device settings and my app MainActivity applies dark theme, then MainActivity starts twice. I did`t find any explanation on why it happens.
SplashActivity very simple
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.splash_screen_layout)
Handler(Looper.getMainLooper()).postDelayed({
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
Log.i("SPLASH","Main activity started")
finish()
}, 2000)
}
}
Main Activity has the following function to check what theme is saved in app settings and apply it:
Function
private fun checkDarkMode(){
when (MainSettings(this).darkMode) {
0 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
delegate.applyDayNight()
}
1 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
delegate.applyDayNight()
}
2 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
delegate.applyDayNight()
}
}
}
So here if dark mode is turned off in device settings, then handler code will be executed twice for AppCompatDelegate.MODE_NIGHT_YES, for others just once as intended.
It also happens vise versa, if device dark on, then code executes twice for AppCompatDelegate.MODE_NIGHT_NO.
As I said I didn`t find any explanation or solution, so what I did is just defined handler as val and cancelled everything for it in onPause or onDestroy of SplashActivity
private val handler = Handler(Looper.getMainLooper())
override fun onPause() {
super.onPause()
handler.removeCallbacksAndMessages(null)
}
So my question is why it happens and is there another way to avoid it?
I would take a look at the source for AppCompatDelegate
which is here (take a lot around line 201 for the part where it recreates the activity).
I can't offer a direct solution to your problem but an alternative would be to just inherit from one of the DayNight
themes (although you do lose the ability to have a night theme on anything below Android 10, but in my opinion it makes things a lot easier).
Edit: You might be able to perform your checkDarkMode
method in an Application
class, this should hopefully set the correct mode before any activites are created (thus avoiding them being created again when it changes).
public class MyApplication extends Application {
public void onCreate() {
super.onCreate();
checkDarkMode()
}