简体   繁体   中英

Singleton Activity Class getInstance() Returns Null

I have an activity like:

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

When the app starts, LogCat will report: Never mind:

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

But later on in my other activity,

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

will produce a null pointer exception for trying to access updateList() on a "null object reference". I also threw in a Log.i() right before the 2nd line to confirm that it's indeed a null...

Can somebody explain why?

Edit 1. Watered down version of MainActivity ( onCreate() not watered down):

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

First off- never do this. Its a memory leak. Never hold a static reference to an Activity or Context. If you need to update data in it, that data may be appropriate for a singleton, but an Activity NEVER is.

Secondly- are you sure that the list activity was ever shown? If not then the variable would be null. That also includes the case of the app being killed and later relaunched from the saved intent in the recents menu.

Although this is not a memory leak, this is definitely not a correct android design pattern. The problem is you are assuming that when you pass the line:

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

your activity has been created. THIS IS WRONG!

In other words, running startActivity method does not INCLUDE running onCreate method of the activity that is supposed to run.

The above line only sends a message to the main looper to run the next activity at a later time (possibly a few msec).


Again: this is not a memory leak - but it is definitely a poor way of managing memory . By keeping a reference to your activity you keep your UI components in the memory. You need look into a more appropriate design pattern to satisfy your need.

One possible way to have a flag in an external singleton with some THINGS_TO_BE_DONE_UPON_CREATING_LIST_VIEW data. And check these values in your onCreate and update your list and etc according to this information rather than keeping a static reference to the activity itself. This is very crude example:

Class MySingleton{
    public static String[] files;
}

in your ListView :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM