简体   繁体   English

Android Handler Looper Dark Theme 行为

[英]Android Handler Looper Dark Theme behavior

I experienced interesting behavior with Handler(Looper.getMainLooper()).我经历了 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.例如,如果在设备设置中关闭了深色模式并且我的应用 MainActivity 应用了深色主题,那么 MainActivity 会启动两次。 I did`t find any explanation on why it happens.我没有找到任何解释为什么会发生。

SplashActivity very simple SplashActivity 非常简单

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: Main Activity 具有以下 function 以检查应用设置中保存的主题并应用它:

Function 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.因此,如果在设备设置中关闭了暗模式,则处理程序代码将为 AppCompatDelegate.MODE_NIGHT_YES 执行两次,而其他人则按预期执行一次。

It also happens vise versa, if device dark on, then code executes twice for AppCompatDelegate.MODE_NIGHT_NO.反之亦然,如果设备变暗,则代码会为 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正如我所说,我没有找到任何解释或解决方案,所以我所做的只是将处理程序定义为 val 并在 SplashActivity 的 onPause 或 onDestroy 中取消了它的所有内容

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).我会看一下这里AppCompatDelegate的源代码(在第 201 行周围花很多时间来重新创建活动的部分)。

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).我无法为您的问题提供直接解决方案,但另一种选择是DayNight主题之一继承(尽管您确实无法在 Android 10 以下的任何内容上拥有夜间主题,但在我看来,它使事情变得容易得多)。

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).编辑:您可能能够在Application class 中执行您的checkDarkMode方法,这应该希望在创建任何活动之前设置正确的模式(从而避免在更改时再次创建它们)。

public class MyApplication extends Application {

public void onCreate() {
    super.onCreate();
    checkDarkMode()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM