静态单例未在活动中初始化。可能有什么不对?

时间:2012-06-07 22:57:38

标签: android nullpointerexception

我正在尝试追踪一个新的空指针异常,它出现在我的ACRA日志中,而且我无法重现。这是相关的代码:

public class MyApplication extends Application {
   public void onCreate() {
       DataManager.instance().initializeData(this);
   }
}

public class DataManager {
    private static DataManger instance = new DataManger();
    private List<DataModel> dataModels;
    private List<I_Callback> callbacks = new ArrayList<I_Callback>();
    private boolean isInitialized = false;

    private DataManager(){}

    public static DataManager instance() {
       return instance;
    }

    public void initializeData(Context context) {
        new DataManagerInitializer().execute(context);
    }

    public void setDataModels(List<DataModel> models) {
        dataModels = models;
    }

    public void synchronized registerInitializeCallbacks(I_Callback callback) {
        if (isInitialized) {
             callback.executeCallback();
        } else {
             callbacks.add(callback);
        }
    }

    public void synchronized setInitialized() {
        isInitialized = true;
        for (I_Callback callback:callbacks) {
             callback.executeCallback();
        }
        callbacks.clear();
    }
}

public class DataManagerInitializer extends AsyncTask<Context, Void, Void>{
    protected Void doInBackground(Context... contexts){
        List<DataModel> dataModels = new ArrayList<DataModel>();
        /*various code to create DataModel objects and add to dataModels list*/
        DataManager.instance().setDataModels(dataModels);
        return null;
    }

    protected void onPostExecute(Void result) {
        DataManager.instance().setInitialized();
    }
}

public class ActivityA extends Activity implements I_Callback{
     public void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.graphical_layout);
        DataManager.instance().registerInitializeCallbacks(this);
     }

     public void executeCallback() {
        /* wire up button to call Activity B */
     }
}

public class ActivityB extends Activity {
     public void onCreate(Bundle savedInstanceState) {
         List<DataModel> dataModels = DataManager.instance().getDataModels();

         /* The following line of code throws a null pointer exception 
            in the stack trace*/
         for (int i=0; i < dataModels.size(); i++){
              /* do something with the data model */
         }
     }
}

为了更简单地分解上述内容,启动了应用程序,启动了数据管理器单例的初始化。 ActivityA,主要活动,启动并等待数据管理器完成初始化,然后允许任何操作,连接任何事件等。从ActivityA,它不可能在没有执行回调方法的情况下到达ActivityB,而ActivityB只能从ActivityA。数据模型列表在DataManager中为空的唯一方法是它尚未初始化,但我很难看到这是如何实现的。关于我的空指针如何发生的任何建议?

2 个答案:

答案 0 :(得分:2)

private static DataManger instance = new DataManger();

...


public static DataManager instance() {
   return instance;
}

问题出在哪里。所以你的instance变量正在收集垃圾。因为它在声明时被实例化,所以它没有被适当地重新实例化。所以,试试这个:

private static DataManger instance = null;

...


public static DataManager instance() {
    if (instance == null){
        instance = new DataManager();
    } 
    return instance;
}

这将确保调用instance()(通常称为getInstance(),但这只是约定),将返回datamanager的有效单个实例。尽量避免使用声明来实例化全局变量,以避免出现这个特定问题。

答案 1 :(得分:1)

我们假设:

you are interacting with the Activity B

按主页按钮:

start playing with other apps (consuming memory)

在某些时候需要记忆,它会开始垃圾收集对象,包括你的“实例”。

如果在您启动应用程序时发生这种情况,框架将恢复活动B并且npe将会发生。

如果实例为空,则需要重新创建实例(在活动B中)。