TL; DR: Dans la plupart des applications, il est logique de prendre une décision architecturale consciente explicite que, en cas de mort d'un processus, l'application redémarre simplement à partir de zéro sans essayer de restaurer l'état. Et dans ce cas Serializable
, Parcelable
et d'autres Bundle
ne sont pas nécessaires.
Si au moins une activité de l'application se situe entre onStart()
et onStop()
, alors il est garanti que l'activité, et donc le processus dans lequel l'activité vit, sont sûrs. Dans d'autres cas, le systÚme d'exploitation peut tuer le processus de demande à tout moment.
Je n'ai pas eu à implémenter un traitement transparent (c'est-à -dire invisible pour l'utilisateur) de la mort d'un processus dans une application réelle. Mais cela semble tout à fait réalisable, a décrit un exemple de travail: https://github.com/mychka/resurrection .
L'idée est d' onSaveInstanceState()
enregistrer l'intégralité de l'état de l'application dans chaque activité et onCreate()
, si le processus a été interrompu, de restaurer:
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)
}
}
Afin de simuler l'arrĂȘt d'un processus, vous pouvez minimiser l'application et utiliser la commande
adb shell am kill org.resurrection
Si nous dĂ©cidons de gĂ©rer la mort du processus, les frais gĂ©nĂ©raux suivants peuvent ĂȘtre notĂ©s.
Complication du code.
- , , , . , , - . - : , , .
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
Pour ĂȘtre sĂ»r, vous devez plonger dans le code source d'Android. S'il y a une option «Ne pas garder les activitĂ©s», alors il y a un code dans le noyau Android qui peut dĂ©truire «doucement» les activitĂ©s. Avec une forte probabilitĂ©, vous pouvez trouver un scĂ©nario dĂ©licat lorsque ce code est appelĂ© et, par consĂ©quent, androidx.lifecycle.ViewModel
entraĂźnera un crash, contrairement onSaveInstanceState()
. Mais dans la vraie vie, apparemment, androidx.lifecycle.ViewModel
vous pouvez toujours l' utiliser en toute sécurité.