由于配置更改而重新创建 Activity 的静态成员时会发生什么
What happens to static members of an Activity when it is recreated because of config changes
我想在我的 Activity
中创建一个静态演示者对象,这样当 Activity
由于配置更改而重新创建时,它将保留演示者实例并且我的业务逻辑不会做作的。
我的Activity
的代码是:
public class HomeActivity extends AppCompatActivity {
public static HomePresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
if (presenter == null){
presenter = new HomePresenter();
}
}
}
您的代码会起作用,演示者会活着,但是请不要这样做。
关键字 'static' 表示该字段的值将附加到 class,而不是它的实例。因此,例如,如果您将拥有自己的 HomeActivity,那么您将转到 SomeElseActivity,然后转到新的 HomeActivity(您将返回堆栈 HomeActivity -> SomeElseActivity -> HomeActivity),对于新的 HomeActivity,您将拥有与旧的相同的演示者。因此,您将有一个共享演示者用于 2 个独立的 HomeActivity 实例。此外,如果您在演示者中有一些状态,在这种情况下您的应用程序将遇到很多问题。
我建议您删除 'static' 关键字。如果您的演示者有状态,需要在配置更改期间保存,请尝试以下两种选择之一:
1) 在演示者中创建 onSaveInstanceState 和 onRestoreInstance 状态,并在适当的 activity 方法中调用它们
2) 创建没有 ui 但带有标志 'retain instace' 的片段(setRetainInstance 方法),此片段将保留对您的演示者的引用。
In short, the static object remains, and it gets its birth when you class is loaded into memory, and never goes away until your app dies, or when the class is unloaded.
在 JVM 语言中,编译器通过 embedding bytecode 中的值优化 static 字段] 而不是在运行时计算值。
当您启动 JVM 并首次加载 class 时(这是在 class 以任何方式首次被引用时由 class 加载程序完成的)任何静态块或字段 'loaded' 进入 JVM 并变得可访问。
So the static variable lives in the circle in the snapshot, and it is ignorant of whatever config changes, it is there, no matter what happens and as long as as the class is loaded.
静态实例不会发生任何事情。但是如果您不删除对静态呈现器的引用,这样做可能会泄漏内存(请参阅 Avoiding memory leaks)。
我会建议另一种方法。当 Activity
由于配置更改(例如旋转)而被销毁时,覆盖 onRetainNonConfigurationInstance()
以保留对象。并在配置更改后使用 getLastNonConfigurationInstance()
获取完全相同的对象。
public class HomeActivity extends AppCompatActivity {
public HomePresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
presenter = (HomePresenter)getLastNonConfigurationInstance();
if (presenter == null){
presenter = new HomePresenter();
}
}
@Override
public Object onRetainNonConfigurationInstance() {
return presenter;
}
}
您还可以使用 Fragment
在配置更改期间使对象保持活动状态,请参阅 RetainingAnObject。
我想在我的 Activity
中创建一个静态演示者对象,这样当 Activity
由于配置更改而重新创建时,它将保留演示者实例并且我的业务逻辑不会做作的。
我的Activity
的代码是:
public class HomeActivity extends AppCompatActivity {
public static HomePresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
if (presenter == null){
presenter = new HomePresenter();
}
}
}
您的代码会起作用,演示者会活着,但是请不要这样做。
关键字 'static' 表示该字段的值将附加到 class,而不是它的实例。因此,例如,如果您将拥有自己的 HomeActivity,那么您将转到 SomeElseActivity,然后转到新的 HomeActivity(您将返回堆栈 HomeActivity -> SomeElseActivity -> HomeActivity),对于新的 HomeActivity,您将拥有与旧的相同的演示者。因此,您将有一个共享演示者用于 2 个独立的 HomeActivity 实例。此外,如果您在演示者中有一些状态,在这种情况下您的应用程序将遇到很多问题。
我建议您删除 'static' 关键字。如果您的演示者有状态,需要在配置更改期间保存,请尝试以下两种选择之一:
1) 在演示者中创建 onSaveInstanceState 和 onRestoreInstance 状态,并在适当的 activity 方法中调用它们
2) 创建没有 ui 但带有标志 'retain instace' 的片段(setRetainInstance 方法),此片段将保留对您的演示者的引用。
In short, the static object remains, and it gets its birth when you class is loaded into memory, and never goes away until your app dies, or when the class is unloaded.
在 JVM 语言中,编译器通过 embedding bytecode 中的值优化 static 字段] 而不是在运行时计算值。
当您启动 JVM 并首次加载 class 时(这是在 class 以任何方式首次被引用时由 class 加载程序完成的)任何静态块或字段 'loaded' 进入 JVM 并变得可访问。
So the static variable lives in the circle in the snapshot, and it is ignorant of whatever config changes, it is there, no matter what happens and as long as as the class is loaded.
静态实例不会发生任何事情。但是如果您不删除对静态呈现器的引用,这样做可能会泄漏内存(请参阅 Avoiding memory leaks)。
我会建议另一种方法。当 Activity
由于配置更改(例如旋转)而被销毁时,覆盖 onRetainNonConfigurationInstance()
以保留对象。并在配置更改后使用 getLastNonConfigurationInstance()
获取完全相同的对象。
public class HomeActivity extends AppCompatActivity {
public HomePresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
presenter = (HomePresenter)getLastNonConfigurationInstance();
if (presenter == null){
presenter = new HomePresenter();
}
}
@Override
public Object onRetainNonConfigurationInstance() {
return presenter;
}
}
您还可以使用 Fragment
在配置更改期间使对象保持活动状态,请参阅 RetainingAnObject。