0

整个原始问题都是基于一个错误。您永远不能final static FIELD在构造函数中分配常量的值。如果可以的话,每次创建类的新实例时,静态 FIELD 的值都会发生变化。不是很最终!

相反,我可以做我一直在做的事情(并且可能会造成内存泄漏,我有很多东西要学),即使用一个static(但不是final)字段来指向我的 Activity 的最新实例(参见下面的代码示例)。正如下面关于内存泄漏的评论所指出的那样,我几乎可以肯定通过保留对旧 Activity 对象的引用来造成内存泄漏。

所以我最初的问题的答案真的归结为:这不是一件好事,因为将其他对象引用传递给我当前的 Activity 对象可以让他们阻止系统垃圾收集我的旧 Activity 对象!

无论如何,这是我原来的问题中提到的代码,答案和评论仍然在这里,所以其余的内容仅供参考。

public class MyActivity extends Activity {
  public final static MyActivity uI;
  public static MyActivity mostRecentUI;

  private MyActivity() { // this is the constructor
      // In my original post I had:
      // uI = this;  
      // but this is illegal code.  `final static anything;` cannot be assigned a 
      // value in the constructor, because it could be assigned a different value
      // each time the class is instantiated!  

      // Instead the best I can do is
      mostRecentUIobject = this;
      // and this name better describes what this static variable contains
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
  }
}

添加了 4/15:@dmon 甚至评论构造函数将不会运行。它会,任何有任何疑问的人都可以运行这个测试活动:

public class TestActivityConstructor extends Activity {
    static long refTime = System.currentTimeMillis();
    static String staticExecution = "Static never executed\n";
    static String constructorExecution = "Constructor never executed\n";
    static String onCreateExecution = "onCreate never executed\n";

    static {
        staticExecution = "Static Execution at " + (System.currentTimeMillis() - refTime) + " ms\n";
    }

    public TestActivityConstructor() {
        constructorExecution = "Constructor Execution at " + (System.currentTimeMillis() - refTime) + "ms \n";
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        onCreateExecution = "onCreate Execution at " + (System.currentTimeMillis() - refTime) + "ms \n";
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ((TextView) findViewById(R.id.TV)).setText(staticExecution + constructorExecution + onCreateExecution);
    }
}

显然,您需要一个带有名为 TV 的 textview 的简单 layout.xml。无需权限。您甚至可以享受旋转 android 以查看重新创建的应用程序的乐趣,这表明每次旋转屏幕时都会重新运行构造函数和 onCreate,但重新创建 Activity 时不会重做静态分配。

4

3 回答 3

3

基本上回答你的问题标题的主要部分......

可以在 Activity 中使用私有构造函数...?

不。

我假设您是从以前的 Java 角度进入 Android 的,但是要了解 Android 的一件事是,Activity该类是少数几个特殊情况类之一,应该按照设计的方式继续工作。

当涉及到类时,不要关心构造函数的概念,Activity只需遵循足够有效的设计方法和应用程序基础即可。

如果您有在 Android 框架中不起作用的特定要求,请发布带有示例代码的问题,有人会解释如何解决它。

编辑:根据您对问题的更新...

public final static MyActivity uI;

有了这个,我可以将“用户界面”对象作为 MyActivity.uI 引用,而不必通过调用链传递引用。

说真的……不要那样做。有完全充分、实用且安全的机制,可用于以最少的代码轻松处理任何情况,而不会以您尝试做事的方式“破坏”模型。

重复我在原始答案中所说的话 - AndroidActivity类是一个特例。的实例Activity及其方法/字段并不意味着可以由任何其他外部类直接访问。

如果您简单地接受 Android 框架的基础知识,您将帮自己一个忙,并省去很多麻烦。编写 Android 应用程序可能会涉及 Java,但并非所有“通用”Java 概念都适用,尤其是一些核心组件,例如Activity.

于 2012-04-14T18:51:53.933 回答
2

由于活动管理器实例化了您的 Acitivity,您可能不会调用您的构造函数 - 不确定这是否适用于私有构造函数 + final。

还有一些东西不能在构造时使用,因为你的活动在onCreate被调用之前没有完全初始化(比如 SharedPreferences)。

于 2012-04-14T18:28:03.563 回答
0

好吧,您的构造函数可能会被调用。但是,没有“单一”活动(不是真的),因此设置一个引用活动实例的最终变量并不是解决此问题的正确方法。例如,如果您支持方向更改,则该活动将被重新创建(正如您所发现的那样),并且您的最终参考是错误的。此外,由于您引用了已销毁的活动(不再使用),因此您刚刚泄露了该活动。恐怕您将不得不通过创建和实例化视图的常规方法。

无论如何,我认为一个更好的问题是你想要完成的事情的一个例子(以及为什么你觉得它如此麻烦),而不是试图回避已经存在的东西。

于 2012-04-15T23:00:21.667 回答