TL; DR: In den meisten Anwendungen ist es sinnvoll, eine explizite bewusste Architekturentscheidung zu treffen, bei der die Anwendung im Falle eines Prozesstodes einfach von Grund auf neu gestartet wird, ohne zu versuchen, den Status wiederherzustellen. Und in diesem Fall Serializable
werden Parcelable
andere Bundle
nicht benötigt.
Befindet sich mindestens eine AnwendungsaktivitÀt zwischen onStart()
und onStop()
, ist garantiert, dass die AktivitĂ€t und damit der Prozess, in dem die AktivitĂ€t ausgefĂŒhrt wird, sicher sind. In anderen FĂ€llen kann das Betriebssystem den Anwendungsprozess jederzeit beenden.
Ich musste keine transparente (dh fĂŒr den Benutzer unsichtbare) Verarbeitung des Todes eines Prozesses in einer realen Anwendung implementieren. Aber es scheint durchaus machbar zu sein, skizzierte ein funktionierendes Beispiel: https://github.com/mychka/resurrection .
Die Idee ist, onSaveInstanceState()
den gesamten Status der Anwendung in jeder AktivitÀt zu speichern und onCreate()
, falls der Prozess abgebrochen wurde, wiederherzustellen:
abstract class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ResurrectionApp.ensureState(savedInstanceState)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
ResurrectionApp.STATE.save(outState)
}
}
Um das Beenden eines Prozesses zu simulieren, können Sie die Anwendung minimieren und den Befehl verwenden
adb shell am kill org.resurrection
Wenn wir uns entscheiden, den Tod des Prozesses zu behandeln, kann der folgende Aufwand festgestellt werden.
Code-Komplikation.
- , , , . , , - . - : , , .
Serializable
/Parcelable
.- â , . ,
loading == true
. , , loading
false
. TCP-, . - ,
Activity#onCreate()
â , â .
, , , . , , , - .
Activity#onSaveInstanceState()
. (, Activity#isChangingConfigurations == true
, , .) , , - .
. 1, . / .
. , , , , , - .
, , : , . , , , .
, . , , foreground . , .
( ) , , .
. (02.03.2020) : Facebook, Twitter, WhatsApp, Chrome, Gmail, Yandex.Maps. : Yandex.Navigator, YouTube, -, Skype.
, , . , , . : , .
https://github.com/mychka/life-from-scratch
BaseActivity
. LoginActivity
. "NEXT". DashboardActivity
. .
adb shell am kill org.lifefromscratch
. , DashboardActivity
LoginActivity#loginShownAt
, .
. , . , :
abstract class BaseActivity : AppCompatActivity() {
companion object {
init {
if (!appStartedNormally) {
APP.startActivity(
APP.getPackageManager().getLaunchIntentForPackage(
APP.getPackageName()
)
);
System.exit(0)
}
}
}
}
. , -.
. , .
class BinderReference<T>(val value: T?) : Binder()
Parcel
. ,
class MyNonSerializableData(val os: OutputStream)
val parcel: Parcel = Parcel.obtain()
val obj = MyNonSerializableData(ByteArrayOutputStream())
parcel.writeStrongBinder(BinderReference(obj))
parcel.setDataPosition(0)
val obj2 = (parcel.readStrongBinder() as BinderReference<*>).value
assert(obj === obj2)
android.os.Binder
https://habr.com/ru/post/274635/
. . , . :
const val DEFAULT_BUNDLE_KEY = "com.example.DEFAULT_BUNDLE_KEY.cr5?Yq+&Jr@rnH5j"
val Any?.bundle: Bundle?
get() = if (this == null) null else Bundle().also { it.putBinder(DEFAULT_BUNDLE_KEY, BinderReference(this)) }
inline fun <reified T> Bundle?.value(): T =
this?.getBinder(DEFAULT_BUNDLE_KEY)?.let {
if (it is BinderReference<*>) it.value as T else null
} as T
inline fun <reified Arg> Fragment.defaultArg() = lazy<Arg>(LazyThreadSafetyMode.NONE) {
arguments.value()
}
. :
findNavController(R.id.nav_host_fragment).navigate(
R.id.bbbFragment,
MyNonSerializableData(ByteArrayOutputStream()).bundle
)
val data: MyNonSerializableData by defaultArg()
â androidx.lifecycle.ViewModel
. , , destroy , configuration change, https://developer.android.com/reference/androidx/activity/ComponentActivity.html#onRetainCustomNonConfigurationInstance()
, , , . ViewModel
.
BinderReference
, androidx.lifecycle.ViewModel
, onSaveInstanceState(outState)
/onCreate(savedInstanceState)
. view model .
UPD: kamer Dimezis , , 2.3 (API 9). . (, finish()
), configuration change. :
https://stackoverflow.com/questions/7536988/android-app-out-of-memory-issues-tried-everything-and-still-at-a-loss/7576275#7576275
https://stackoverflow.com/questions/11616575/android-not-killing-activities-from-stack-when-memory-is-low/11616829#11616829
:
https://issuetracker.google.com/issues/36934944
Um sicher zu sein, mĂŒssen Sie in den Quellcode von Android eintauchen. Wenn es eine Option "AktivitĂ€ten nicht behalten" gibt, gibt es im Android-Kernel einen Code, der AktivitĂ€ten "sanft" zerstören kann. Mit hoher Wahrscheinlichkeit können Sie sich ein schwieriges Szenario einfallen lassen, wenn dieser Code aufgerufen wird, und dementsprechend androidx.lifecycle.ViewModel
im Gegensatz zu einem Absturz fĂŒhren onSaveInstanceState()
. Aber im wirklichen Leben können Sie es anscheinend androidx.lifecycle.ViewModel
immer noch sicher verwenden.