代码之家  ›  专栏  ›  技术社区  ›  mxk

活动类中的静态字段是否保证能在创建/销毁周期内生存?

  •  15
  • mxk  · 技术社区  · 15 年前

    我经常遇到这样一个问题:在一个活动的几个调用之间(即经历几个onCreate()/OnDelete()循环),我必须保留状态。不幸的是,Android对这一点的支持真的很差。

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

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

    这不意味着当活动正在经历创建/销毁循环时,类已经被类加载器移除并重新加载了吗?还有什么能 静止的 字段以前引用对象时突然变为空?

    2 回复  |  直到 10 年前
        1
  •  13
  •   JohnnyLambada    10 年前

    这个答案的第一部分真的很古老——参见下面的 正确的 做这件事的方法

    可以使用应用程序对象存储应用程序持久对象。 This 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();
        }
    }
    

    这个 正确的 方式 :

    当第一次写下这个答案时,活动生命周期的文档不如现在的好。阅读 Saving Activity State 活动文档的部分帮助我们了解Android希望我们如何保存状态。基本上,有两种情况下您的活动开始:(1)作为一个新的活动和(2)由于配置更改或当它被破坏后,由于内存压力重新创建。当您的活动因为是新活动而启动时,则saveInstanceState为空。否则不为空。如果它为空,那么您的活动应该从头开始初始化。片段与活动非常相似,我为我的 AnDevCon-14 slide deck . 你也可以看看 sample code 更多详细信息,请参阅我的andevcon-14演示。

    重新编写上一个示例看起来像下面的代码。我确实稍微改变了语义——在第二个版本中,我假设字符串 thing 特定于特定 android task 在前面的示例中,它是不明确的。如果您确实想为多个Android任务保留相同的数据,那么使用应用程序对象或另一个singleton仍然是您的最佳选择。

    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
  •  0
  •   haseman    15 年前

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

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

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