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

2022-09-03 07:03:57

我经常遇到这样的问题,即我必须在活动的多次调用之间保持状态(即经历几个onCreate()/onDelete()周期)。不幸的是,Android对这样做的支持真的很差。

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

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

这是否意味着在活动经历创建/销毁周期时,类加载器已被类加载器删除并重新加载?否则,当静态字段之前引用对象时,它怎么会突然变成 NULL 呢?


答案 1

这个答案的第一部分真的很旧 - 请参阅下面的正确方法。

可以使用 Application 对象来存储应用程序持久性对象。这个Android常见问题解答也讨论了这个问题。

像这样:

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();
    }
}

正确的方法

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

重做我之前的示例将类似于下面的代码。我确实稍微改变了语义 - 在第二个版本中,我假设字符串特定于特定Android任务中的活动,在前面的示例中它是模棱两可的。如果您确实想为多个Android任务保留相同的数据,那么使用Appplication对象或其他单例仍然是您最好的选择。thing

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);
    }
}

答案 2

另一种也是邪恶的保留静态数据的方法是让你活动启动一个单例类。此单例将保持对自身的静态引用。

class EvilSingleton{
    private static EvilSingleton instance;

    //put your data as non static variables here

    public static EvilSingleton getInstance()
    {
        if(instance == null)
            instance = new EvilSingleton();
        return instance;
    }
}

在活动的 onCreate() 方法中,您可以访问/构建单例和您可能需要的任何数据。这样,您的活动或应用程序可以被破坏或重新创建任意次数,只要您的进程的内存空间被保留,您应该没问题。

这是一个邪恶的颠覆性黑客,所以没有承诺;-)


推荐