Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 活动类中的静态字段是否保证超过创建/销毁周期?_Java_Android_Static_Classloader - Fatal编程技术网

Java 活动类中的静态字段是否保证超过创建/销毁周期?

Java 活动类中的静态字段是否保证超过创建/销毁周期?,java,android,static,classloader,Java,Android,Static,Classloader,我经常遇到这样一个问题:我必须在一个活动的多次调用之间保持状态(例如,经历几个onCreate()/onDelete()周期)。不幸的是,Android对这方面的支持非常差 作为一种保存状态的简单方法,我认为,由于类加载器只加载一次类,因此在静态Bundle字段中存储活动的多个实例之间共享的临时数据是安全的 然而,有时候,当实例A创建静态捆绑包并在其中存储数据,然后被销毁,实例B尝试从中读取数据时,静态字段突然为空 这是否意味着在活动经历创建/销毁周期时,类加载器已删除并重新加载了该类?否则,静

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

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

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


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

这个答案的第一部分真的很老了——请参见下面的正确方法

您可以使用应用程序对象来存储应用程序持久对象。也谈到这个问题

大概是这样的:

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演示文稿,了解更多详细信息

修改我前面的示例将类似于下面的代码。我确实对语义做了一些修改——在第二个版本中,我假设字符串
thing
是特定于特定活动的,在前面的示例中,它是不明确的。如果您确实希望为多个android任务保留相同的数据,那么使用应用程序对象或另一个单例仍然是您的最佳选择

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

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

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;
    }
}
在activity的onCreate()方法中,您可以访问/构建singleton和可能需要的任何数据。这样,您的活动或应用程序可以被销毁或重新创建任意次数,只要您的进程的内存空间被保留,您就应该可以了


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

我不确定你的问题的答案,但我知道Android开发人员建议你不要不必要地保留静态引用,因为它们容易发生内存泄漏:嗯,那篇文章是关于泄漏上下文的。如果通过静态引用可以很好地访问上下文,那么这只是一个问题,例如视图,但bundle(据我所知?)就不是这样。但一般来说,我会假设一个静态引用,一旦类被加载,就和应用一样长,这在Android中似乎不是真的。。。只要它不变成神客体反模式呵呵,我以前就没听说过神客体[1]模式。很有趣的事。我可能应该说这只是一个简单的例子。除了一个普通的应用程序之外,您的应用程序类还应该有其他保存真实数据的对象,而不是数据本身的存储库。在Android中,它是存储其他对象的方便场所。[1] 我正在从修改应用程序类转向使用单例。请参见Dianne Hackbod在此处的回答:在文档中如何>>>公共静态字段/方法使跨活动/服务访问数据的另一种方法是使用公共静态字段和/或方法。您可以从应用程序中的任何其他类访问这些静态字段。为了共享一个对象,创建对象的活动会设置一个静态字段来指向这个对象,而任何其他想要使用这个对象的活动都会访问这个静态字段。我很困惑。你提出了另一种方法。这是否意味着OP问题的答案是“否”?我不应该在活动中使用静态字段?谢谢,但不谢谢。我和单身汉玩得已经够开心了。这是所有设计模式中被滥用最多的一种,在大多数情况下,我看到它被使用,它实际上是一种反模式。这很公平。这不是一种模式,我经常在日程压力很大的情况下使用它们,但我同意,在一个大型、维护良好的项目中,它们最多应该少用。在为Singleton辩护时,Android中有一个很好的使用案例:SqliteOpenHelper实例。除此之外,我同意你们的观点。