diff --git a/app/build.gradle b/app/build.gradle
index 564e4cdb3..1b19165ab 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -145,7 +145,6 @@ dependencies {
     implementation 'io.reactivex:rxandroid:1.2.1'
     implementation 'io.reactivex:rxjava:1.3.8'
     implementation 'com.jakewharton.rxrelay:rxrelay:1.2.0'
-    implementation 'com.f2prateek.rx.preferences:rx-preferences:1.0.2'
     implementation 'com.github.pwittchen:reactivenetwork:0.13.0'
 
     // Network client
@@ -188,6 +187,10 @@ dependencies {
     implementation 'com.github.inorichi.storio:storio-sqlite:8be19de@aar'
     implementation 'io.requery:sqlite-android:3.31.0'
 
+    // Preferences
+    implementation 'com.f2prateek.rx.preferences:rx-preferences:1.0.2'
+    implementation 'com.github.tfcporciuncula:flow-preferences:1.1.1'
+
     // Model View Presenter
     final nucleus_version = '3.0.0'
     implementation "info.android15.nucleus:nucleus:$nucleus_version"
diff --git a/app/src/main/java/eu/kanade/tachiyomi/App.kt b/app/src/main/java/eu/kanade/tachiyomi/App.kt
index d2a7f69bf..3be071b38 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/App.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/App.kt
@@ -12,7 +12,6 @@ import androidx.lifecycle.ProcessLifecycleOwner
 import androidx.multidex.MultiDex
 import eu.kanade.tachiyomi.data.notification.Notifications
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
-import eu.kanade.tachiyomi.data.preference.getOrDefault
 import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
 import eu.kanade.tachiyomi.util.system.LocaleHelper
 import org.acra.ACRA
@@ -72,7 +71,7 @@ open class App : Application(), LifecycleObserver {
     @Suppress("unused")
     fun onAppBackgrounded() {
         val preferences: PreferencesHelper by injectLazy()
-        if (preferences.lockAppAfter().getOrDefault() >= 0) {
+        if (preferences.lockAppAfter().get() >= 0) {
             SecureActivityDelegate.locked = true
         }
     }
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
index 36e98483b..0e2a974ac 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
@@ -7,6 +7,7 @@ import android.os.Environment
 import androidx.preference.PreferenceManager
 import com.f2prateek.rx.preferences.Preference
 import com.f2prateek.rx.preferences.RxSharedPreferences
+import com.tfcporciuncula.flow.FlowSharedPreferences
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
 import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
@@ -15,6 +16,7 @@ import java.io.File
 import java.text.DateFormat
 import java.text.SimpleDateFormat
 import java.util.Locale
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 
 fun <T> Preference<T>.getOrDefault(): T = get() ?: defaultValue()!!
 
@@ -36,10 +38,12 @@ private class DateFormatConverter : Preference.Adapter<DateFormat> {
     }
 }
 
+@OptIn(ExperimentalCoroutinesApi::class)
 class PreferencesHelper(val context: Context) {
 
     private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
     private val rxPrefs = RxSharedPreferences.create(prefs)
+    private val flowPrefs = FlowSharedPreferences(prefs)
 
     private val defaultDownloadsDir = Uri.fromFile(
             File(Environment.getExternalStorageDirectory().absolutePath + File.separator +
@@ -51,13 +55,13 @@ class PreferencesHelper(val context: Context) {
 
     fun startScreen() = prefs.getInt(Keys.startScreen, 1)
 
-    fun useBiometricLock() = rxPrefs.getBoolean(Keys.useBiometricLock, false)
+    fun useBiometricLock() = flowPrefs.getBoolean(Keys.useBiometricLock, false)
 
-    fun lockAppAfter() = rxPrefs.getInteger(Keys.lockAppAfter, 0)
+    fun lockAppAfter() = flowPrefs.getInt(Keys.lockAppAfter, 0)
 
-    fun lastAppUnlock() = rxPrefs.getLong(Keys.lastAppUnlock, 0)
+    fun lastAppUnlock() = flowPrefs.getLong(Keys.lastAppUnlock, 0)
 
-    fun secureScreen() = rxPrefs.getBoolean(Keys.secureScreen, false)
+    fun secureScreen() = flowPrefs.getBoolean(Keys.secureScreen, false)
 
     fun hideNotificationContent() = prefs.getBoolean(Keys.hideNotificationContent, false)
 
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt
index 4479eba4f..bc5e3584d 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt
@@ -77,10 +77,4 @@ abstract class BaseActivity : AppCompatActivity() {
 
         secureActivityDelegate.onResume()
     }
-
-    override fun onDestroy() {
-        secureActivityDelegate.onDestroy()
-
-        super.onDestroy()
-    }
 }
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt
index 97071bd88..c0fb69fae 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt
@@ -27,10 +27,4 @@ abstract class BaseRxActivity<P : BasePresenter<*>> : NucleusAppCompatActivity<P
 
         secureActivityDelegate.onResume()
     }
-
-    override fun onDestroy() {
-        secureActivityDelegate.onDestroy()
-
-        super.onDestroy()
-    }
 }
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/security/SecureActivityDelegate.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/security/SecureActivityDelegate.kt
index 756e5eaa9..02ceaae38 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/security/SecureActivityDelegate.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/security/SecureActivityDelegate.kt
@@ -5,30 +5,33 @@ import android.view.WindowManager
 import androidx.biometric.BiometricManager
 import androidx.fragment.app.FragmentActivity
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
-import eu.kanade.tachiyomi.data.preference.getOrDefault
 import java.util.Date
-import rx.Subscription
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
 import uy.kohesive.injekt.injectLazy
 
 class SecureActivityDelegate(private val activity: FragmentActivity) {
 
     private val preferences by injectLazy<PreferencesHelper>()
 
-    private var secureScreenSubscription: Subscription? = null
+    private val uiScope = CoroutineScope(Dispatchers.Main)
 
     fun onCreate() {
-        secureScreenSubscription = preferences.secureScreen().asObservable()
-                .subscribe {
-                    if (it) {
-                        activity.window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
-                    } else {
-                        activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
-                    }
+        preferences.secureScreen().asFlow()
+            .onEach {
+                if (it) {
+                    activity.window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
+                } else {
+                    activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
                 }
+            }
+            .launchIn(uiScope)
     }
 
     fun onResume() {
-        val lockApp = preferences.useBiometricLock().getOrDefault()
+        val lockApp = preferences.useBiometricLock().get()
         if (lockApp && BiometricManager.from(activity).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) {
             if (isAppLocked()) {
                 val intent = Intent(activity, BiometricUnlockActivity::class.java)
@@ -40,14 +43,10 @@ class SecureActivityDelegate(private val activity: FragmentActivity) {
         }
     }
 
-    fun onDestroy() {
-        secureScreenSubscription?.unsubscribe()
-    }
-
     private fun isAppLocked(): Boolean {
         return locked &&
-                (preferences.lockAppAfter().getOrDefault() <= 0 ||
-                        Date().time >= preferences.lastAppUnlock().getOrDefault() + 60 * 1000 * preferences.lockAppAfter().getOrDefault())
+                (preferences.lockAppAfter().get() <= 0 ||
+                        Date().time >= preferences.lastAppUnlock().get() + 60 * 1000 * preferences.lockAppAfter().get())
     }
 
     companion object {
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt
index 45385929a..055a7df02 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt
@@ -9,9 +9,15 @@ import eu.kanade.tachiyomi.util.preference.intListPreference
 import eu.kanade.tachiyomi.util.preference.summaryRes
 import eu.kanade.tachiyomi.util.preference.switchPreference
 import eu.kanade.tachiyomi.util.preference.titleRes
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
 
 class SettingsSecurityController : SettingsController() {
 
+    private val uiScope = CoroutineScope(Dispatchers.Main)
+
     override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
         titleRes = R.string.pref_category_security
 
@@ -36,8 +42,10 @@ class SettingsSecurityController : SettingsController() {
                 defaultValue = "0"
                 summary = "%s"
 
-                preferences.useBiometricLock().asObservable()
-                        .subscribeUntilDestroy { isVisible = it }
+                isVisible = preferences.useBiometricLock().get()
+                preferences.useBiometricLock().asFlow()
+                    .onEach { isVisible = it }
+                    .launchIn(uiScope)
             }
         }