Android Activity 被随机创建和销毁
Android Activity being randomly Created and Destroyed
我不明白 android 活动是如何管理的。
我有一个 activity,我偶尔注意到,当我的应用程序进入后台时,android 会破坏当前 activity 的任何内容(比如 Activity3) 和其他几个单例和对象等。很好。问题是当应用程序恢复时,直觉告诉我,由于 android 已经破坏了 activity 和内存对象或其他对象,那么 android 将完全从 [=40] 重新启动应用程序=]Activity1 这样所有的对象和数据成员都会被正确初始化。
不是这样!
看来,当我的应用程序恢复时,Activity3 被重新创建,并且 onCreate 被调用时使用与之前相同的参数第一次(当它从 Activity2 调用时)只有这一次在 Activity1 和 中初始化的所有单例和其他对象Activity2 已使用默认值重新创建并变得无用。
这怎么安全policy/technique?怎么能android只是随机销毁对象和活动,然后当用户恢复时调用onCreate最近 activity 并希望一切都变得很简单 不必经过正确的启动 procedure/initialization?
更新/解决方案
感谢评论者提供的精彩信息。
根据 ANDROID 文档
onCreate
Bundle: If the activity is being re-initialized after previously being shut down then this Bundle contains the data it most recently supplied in onSaveInstanceState(Bundle). Note: Otherwise it is null.
因此 我最后做的是设置了两个标志。 Bundle 中的 onSaveInstanceState 中的一个,以便知道它是我设置的有效 Bundle。另一个在 class 本身来确定 onCreate 是否因为 recreation 或 Auto-Rotation。因此,在 onCreate 中,我检查了 onSaveInstanceState 是否不为空,检查了 Bundle 标志,并检查了 bInit(默认为 false)。如果两个标志都为真,则意味着 android 转储并破坏了我们的应用程序内存,确保在线性样式应用程序中再次初始化所有内容的最安全方法是重新启动它并启动开头 activity。
public class SomeMiddleActivity extends AppCompatActivity
{
private static boolean bInit = false; // only way it will be false again is if android cleared our memory and we are recreating
@Override
public void onSaveInstanceState(Bundle state)
{
// set a flag so that onCreate knows this is valid
state.putBoolean("StateSaved", true);
super.onSaveInstanceState(state);
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
// this must be called first always for some reason
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
if (savedInstanceState.getBoolean("StateSaved", false) && !bInit)
{
// we were recreated... start app over
Intent intent = new Intent(getApplicationContext(), Startup.class);
startActivity(intent);
finish();
return;
}
}
bInit = true; // this will stay true until android has cleared our memory
.......
}
虽然到目前为止这很有效,但如果有人有不同的建议,请告诉我。我将就此发表另一篇文章。
仅供参考: onSaveInstanceState(Bundle, PersistableBundle) 版本的 onSaveInstanceState 永远不会曾经打电话过,所以我不知道他们为什么要实施它。 (?)
@goldenb @Rishabh 感谢 goldenb 和 Rishabh 的见解。
Android,如果破坏了,还给你处理的工具
移动设备的内存量有限,需要同时在应用程序 运行 之间共享。因此,智能资源分配是必要的。前台的应用程序 运行 由最终用户使用并获得高优先级以获得更好的性能和用户体验。因此,后台应用程序 运行 需要释放资源以满足前台应用程序的内存需求。因此,后台应用程序有时会被破坏(不完全)(在内存不足的情况下)。
Android 活动有像 onSaveInstanceState() 和 onRestoreInstanceState() 这样的回调,它们使您能够保存 Activity 的当前状态(即变量)当它被销毁并在重新创建 Activity 时检索它们。
您可以从这里获得更多信息:How to save and retrieve the state of Activity using onSaveInstanceState and onRestoreInstanceState.
您可以对检索到的状态执行验证,以确保 Activity 的执行与销毁前完全相同。亲自动手后,您会发现它非常简单且合乎逻辑。
在这个问题上给我 50 美分。处理 activity 系统因其后台资源而被杀死的问题的正确方法是 android 中的一个常见问题,根据 Google 的解决方案是:
onPause() is where you deal with the user leaving your activity. Most
importantly, any changes made by the user should at this point be
committed (usually to the ContentProvider holding the data).
重点是我的。但这意味着 Android 生命周期的设计使得在正常情况下 onPause 应该被调用为 Activity 或 Fragment 被发送到后台。他们在几个 android 文档页面中暗示了这一点:
当您的 activity 进入暂停状态时,系统会调用您的 Activity 上的 onPause() 方法,这允许您停止在暂停时不应继续的正在进行的操作(例如视频)或保留任何应永久保存的信息,以防用户继续离开您的应用。
同样值得您注意的是:如果您希望在 Activity recreation 期间恢复视图,您应该设置所有视图的 ID 属性 ;)
Note: In order for the Android system to restore the state of the
views in your activity, each view must have a unique ID, supplied by
the android:id attribute.
PS。
你想知道为什么 onSaveInstanceState(Bundle, PersistableBundle) 没有被调用,一种可能是你没有设置正确的 activity 属性
This is the same as onRestoreInstanceState(Bundle) but is called for
activities created with the attribute persistableMode set to
persistAcrossReboots..
我不明白 android 活动是如何管理的。
我有一个 activity,我偶尔注意到,当我的应用程序进入后台时,android 会破坏当前 activity 的任何内容(比如 Activity3) 和其他几个单例和对象等。很好。问题是当应用程序恢复时,直觉告诉我,由于 android 已经破坏了 activity 和内存对象或其他对象,那么 android 将完全从 [=40] 重新启动应用程序=]Activity1 这样所有的对象和数据成员都会被正确初始化。
不是这样!
看来,当我的应用程序恢复时,Activity3 被重新创建,并且 onCreate 被调用时使用与之前相同的参数第一次(当它从 Activity2 调用时)只有这一次在 Activity1 和 中初始化的所有单例和其他对象Activity2 已使用默认值重新创建并变得无用。
这怎么安全policy/technique?怎么能android只是随机销毁对象和活动,然后当用户恢复时调用onCreate最近 activity 并希望一切都变得很简单 不必经过正确的启动 procedure/initialization?
更新/解决方案
感谢评论者提供的精彩信息。
根据 ANDROID 文档
onCreate
Bundle: If the activity is being re-initialized after previously being shut down then this Bundle contains the data it most recently supplied in onSaveInstanceState(Bundle). Note: Otherwise it is null.
因此 我最后做的是设置了两个标志。 Bundle 中的 onSaveInstanceState 中的一个,以便知道它是我设置的有效 Bundle。另一个在 class 本身来确定 onCreate 是否因为 recreation 或 Auto-Rotation。因此,在 onCreate 中,我检查了 onSaveInstanceState 是否不为空,检查了 Bundle 标志,并检查了 bInit(默认为 false)。如果两个标志都为真,则意味着 android 转储并破坏了我们的应用程序内存,确保在线性样式应用程序中再次初始化所有内容的最安全方法是重新启动它并启动开头 activity。
public class SomeMiddleActivity extends AppCompatActivity
{
private static boolean bInit = false; // only way it will be false again is if android cleared our memory and we are recreating
@Override
public void onSaveInstanceState(Bundle state)
{
// set a flag so that onCreate knows this is valid
state.putBoolean("StateSaved", true);
super.onSaveInstanceState(state);
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
// this must be called first always for some reason
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
if (savedInstanceState.getBoolean("StateSaved", false) && !bInit)
{
// we were recreated... start app over
Intent intent = new Intent(getApplicationContext(), Startup.class);
startActivity(intent);
finish();
return;
}
}
bInit = true; // this will stay true until android has cleared our memory
.......
}
虽然到目前为止这很有效,但如果有人有不同的建议,请告诉我。我将就此发表另一篇文章。
仅供参考: onSaveInstanceState(Bundle, PersistableBundle) 版本的 onSaveInstanceState 永远不会曾经打电话过,所以我不知道他们为什么要实施它。 (?)
@goldenb @Rishabh 感谢 goldenb 和 Rishabh 的见解。
Android,如果破坏了,还给你处理的工具
移动设备的内存量有限,需要同时在应用程序 运行 之间共享。因此,智能资源分配是必要的。前台的应用程序 运行 由最终用户使用并获得高优先级以获得更好的性能和用户体验。因此,后台应用程序 运行 需要释放资源以满足前台应用程序的内存需求。因此,后台应用程序有时会被破坏(不完全)(在内存不足的情况下)。
Android 活动有像 onSaveInstanceState() 和 onRestoreInstanceState() 这样的回调,它们使您能够保存 Activity 的当前状态(即变量)当它被销毁并在重新创建 Activity 时检索它们。
您可以从这里获得更多信息:How to save and retrieve the state of Activity using onSaveInstanceState and onRestoreInstanceState.
您可以对检索到的状态执行验证,以确保 Activity 的执行与销毁前完全相同。亲自动手后,您会发现它非常简单且合乎逻辑。
在这个问题上给我 50 美分。处理 activity 系统因其后台资源而被杀死的问题的正确方法是 android 中的一个常见问题,根据 Google 的解决方案是:
onPause() is where you deal with the user leaving your activity. Most importantly, any changes made by the user should at this point be committed (usually to the ContentProvider holding the data).
重点是我的。但这意味着 Android 生命周期的设计使得在正常情况下 onPause 应该被调用为 Activity 或 Fragment 被发送到后台。他们在几个 android 文档页面中暗示了这一点:
当您的 activity 进入暂停状态时,系统会调用您的 Activity 上的 onPause() 方法,这允许您停止在暂停时不应继续的正在进行的操作(例如视频)或保留任何应永久保存的信息,以防用户继续离开您的应用。
同样值得您注意的是:如果您希望在 Activity recreation 期间恢复视图,您应该设置所有视图的 ID 属性 ;)
Note: In order for the Android system to restore the state of the views in your activity, each view must have a unique ID, supplied by the android:id attribute.
PS。 你想知道为什么 onSaveInstanceState(Bundle, PersistableBundle) 没有被调用,一种可能是你没有设置正确的 activity 属性
This is the same as onRestoreInstanceState(Bundle) but is called for activities created with the attribute persistableMode set to persistAcrossReboots..