我有足够的经验来了解配置更改。我知道如何保存和恢复View
,Activity
,Fragment
或其他任何内容的实例状态,我知道我们应该依赖它,而不是简单地使对象静态化。 / em>的
这个问题是关于字段static
的问题。在"纯Java"将对象声明为static
可以实现在实例之间共享对象。
在android系统中,当重新创建实例并清除其字段时,声明static
字段也是让生存配置更改的快捷方式。
示例:
public class FooFragment extends Fragment {
private static Object sObject;
public void onViewCreated(View view, Bundle savedInstanceState) {
if (savedInstanceState == null) {
sObject = new Object();
sObject.toString();
} else {
sObject.toString();
}
}
}
在这种情况下,{<1}}可以在片段创建时初始化,只在片段重新创建时获取。当我们的类本身不是静态的,设计为基类,或者是sObject
类时会出现问题。
abstract
现在,public abstract class BaseFragment extends Fragment {
protected static Object sObject;
}
public class FooFragment extends BaseFragment {
public void onViewCreated(View view, Bundle savedInstanceState) {
if (savedInstanceState == null) {
sObject = new Object();
sObject.toString();
} else {
sObject.toString();
}
}
}
public class BarFragment extends BaseFragment {
public void onViewCreated(View view, Bundle savedInstanceState) {
if (savedInstanceState == null) {
sObject = new Object();
sObject.toString();
} else {
sObject.toString();
}
}
}
和FooFragment
都会访问(并且不可预测地使用)BarFragment
的同一个实例。这是静止点,但不是我们想要的。我们希望sObject
和FooFragment
拥有他们自己的sObject ;我们只是希望它能够在配置变更和平台驱动的娱乐中幸存下来。
如何为此目标设计基类?
这就是我想出来的,但我确信还有更好的东西。
BarFragment
基本上我保留一个静态地图,按子类名索引。
答案 0 :(得分:1)
基本上,您正在实施全局缓存。您碰巧使用它进行配置更改这一事实只是一个细节。因此,您需要考虑全局缓存的标准内容。例如,考虑HashMap<String, WeakReference<Object>>
,因此如果由于编码错误或未处理的异常导致无法从HashMap
删除对象,则长期影响将是适度的。
就更多特定于Android的注意事项而言,进入该缓存的任何内容都不应该依赖于配置,例如从字符串资源中剔除的字符串的值。这些需要重建,因为配置更改可能会影响它们的价值。
此外,进入该缓存的任何内容都不应取决于预配置更改环境(例如前一个活动所拥有的视图),以帮助减少内存泄漏。
虽然您认为保留的片段不合适,但您可能会考虑查看其实现或其他全局缓存(例如,毕加索的图像缓存)的实现,以了解可能会影响您的其他想法。
答案 1 :(得分:0)
如果您有一个小应用,您的方法将有效。然而,有一些事情会让这很困难。
<强> 1。内存占用:即使您没有使用该屏幕,也会保留每个静态实例。如上所述,如果您的应用程序很小,这不是什么大问题,但如果您的应用程序增长,可能会导致问题。
<强> 2。可测试性:测试静态内容并不好玩:(
可能有更简单的方法来实现您的目标。
选项A 从DB加载。基本上保存尽可能少的状态(可能是您正在查看的数据ID)并在方向更改时加载数据。
选项B 使用IcePick等库可以更轻松地保存状态您可以保存基元,或为对象创建客户转换器(例如,使用GSON将对象转换为JSON)。