1

我正在尝试追踪一个新的空指针异常,该异常出现在我的 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 只能从活动A。DataManager 中数据模型列表为空的唯一方法是它没有被初始化,但我很难看到这是怎么可能的。关于我的空指针如何发生的任何建议?

4

2 回答 2

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(),但这只是约定)将返回数据管理器的有效单个实例。尽量避免用它们的声明来实例化全局变量,以避免这个特定的问题。

于 2012-06-07T23:02:33.613 回答
1

让我们假设:

you are interacting with the Activity B

按主页按钮:

start playing with other apps (consuming memory)

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

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

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

于 2012-06-07T23:15:44.540 回答