我正在尝试追踪一个新的空指针异常,它出现在我的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中为空的唯一方法是它尚未初始化,但我很难看到这是如何实现的。关于我的空指针如何发生的任何建议?
答案 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中)。