Activity类中的静态字段是否保证比创建/销毁周期更长?

Mat*_*ias 16 java static android classloader

我经常遇到一个问题,我必须在一个活动的几次调用之间保持状态(即经历几个onCreate()/ onDelete()循环).不幸的是,Android对此的支持非常糟糕.

作为一种保存状态的简单方法,我认为由于类只被类加载器加载一次,因此在静态Bundle字段中存储在活动的多个实例之间共享的临时数据是安全的.

但是,偶尔,当实例A创建静态包并在其中存储数据,然后被销毁,而实例B尝试从中读取时,静态字段突然变为NULL.

这是否意味着当活动进行创建/销毁循环时,类已被类加载器删除并重新加载?在以前引用对象时,静态字段怎么会突然变为NULL?

Joh*_*ada 15

这个答案的第一部分非常陈旧 - 请参阅下面的正确方法

您可以使用Application对象来存储应用程序持久对象. 这个Android FAQ也讨论了这个问题.

像这样的东西:

public class MyApplication extends Application{
    private String thing = null;

    public String getThing(){
        return thing;
    }

    public void setThing( String thing ){
        this.thing = thing;
    }
}

public class MyActivity extends Activity {
    private MyApplication app;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        app = ((MyApplication)getApplication());

        String thing = app.getThing();
    }
}
Run Code Online (Sandbox Code Playgroud)

正确的方法:

首次编写此答案时,Activity生命周期的文档不如现在好.阅读活动文档中的保存活动状态部分有助于我们了解Android希望我们如何保存状态.从本质上讲,您的活动开始时有两种情况:(1)作为新活动;(2)由于配置更改或在因内存压力而被销毁后重新创建.当您的活动启动时,因为它是一个新活动,则saveInstanceState为null.否则它不是null.如果它为null,那么您的活动应该从头开始初始化.碎片与活动非常相似,我在AnDevCon-14幻灯片中详细介绍了这个概念.您还可以查看我的AnDevCon-14演示文稿的示例代码以获取更多详细信息.

重新编写我之前的示例将类似于下面的代码.我确实稍微改变了语义 - 在第二个版本中我假设字符串thing特定于特定android任务中的活动,在前面的例子中它是不明确的.如果你想为多个android任务保留相同的数据,那么使用Application对象或其他单例仍然是你最好的选择.

public class MyActivity extends Activity {
    private static final String THING = "THING";

    private String thing;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState==null) {
            // First time here (since we last backed out at least)
            thing = initializeThing(); // somehow we init it
        } else {
            // Rehydrate this new instance of the Activity
            thing = savedInstanceState.getString(THING);
        }

        String thing = app.getThing();
    }

    protected void onSaveInstanceState(Bundle outState) {
        outState.putString(THING, thing);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,这是一个非常好的和简单的想法......只要它不会变成上帝对象的反模式 (4认同)