Singleton Activity类getInstance()返回Null

时间:2015-02-18 00:40:55

标签: java android

我的活动如下:

public class ListActivity extends ActionBarActivity {
    private static ListActivity instance;

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

        Log.i("List", "Instance Created");
        instance = this;
        Log.i("List", (instance == null) ? "null" : "not null");
    }

    public static ListActivity getInstance() {
        return instance;
    }
}

当应用程序启动时,LogCat将报告:没关系:

I/List﹕ Instance Created
I/List﹕ not null

但稍后在我的其他活动中,

startActivity(new Intent(MainActivity.getInstance(), ListActivity.class));
ListActivity.getInstance().updateList(files);

将在尝试访问“null对象引用”上的updateList()时产生空指针异常。我也在第二行之前向Log.i()右侧投掷,以确认它确实是空的......

有人可以解释原因吗?

修改1.淡化MainActivity版本(onCreate()未淡化):

public class MainActivity extends ActionBarActivity {
    private static MainActivity instance;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        instance = this;
    }

    public static MainActivity getInstance() {
        return instance;
    }
}

2 个答案:

答案 0 :(得分:3)

首先 - 永远不要这样做。它是一个内存泄漏。永远不要持有对Activity或Context的静态引用。如果您需要更新其中的数据,那么该数据可能适用于单身人士,但活动永远不会。

其次 - 您确定列表活动曾经展示过吗?如果不是,那么变量将为null。这还包括应用程序被杀死并稍后从最近菜单中保存的意图重新启动的情况。

答案 1 :(得分:1)

虽然这不是内存泄漏,但这绝对不是一个正确的android设计模式。问题是你假设当你通过这条线时:

startActivity(new Intent(MainActivity.getInstance(), ListActivity.class));

您的活动已创建。这是错的!

换句话说,运行startActivity方法不会包含运行应该运行的活动的onCreate方法。

上述行只向主循环器发送一条消息,以便稍后(可能是几毫秒)运行下一个活动。


再次: 这不是内存泄漏 - 但它绝对是一种<强>管理内存的方式。通过保持对您的活动的引用,您可以将UI组件保留在内存中。您需要研究更合适的设计模式以满足您的需求。

在外部单例中使用一些THINGS_TO_BE_DONE_UPON_CREATING_LIST_VIEW数据获得标志的一种可能方法。并在onCreate中检查这些值,并根据此信息更新列表等,而不是保留对活动本身的静态引用。这是一个非常粗糙的例子:

Class MySingleton{
    public static String[] files;
}

ListView

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list);
    if (MySingleton.files!=null)
       updateList(MySingleton.files);
}