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 でデータ モデルのリストが null になる唯一の方法は、それが初期化されていないことですが、これがどのように可能であるかを確認するのに苦労しています。私のヌルポインターがどのように発生したかについての提案はありますか?

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)

ある時点でメモリが必要になり、「インスタンス」を含むオブジェクトのガベージコレクションが開始されます。

アプリを起動したときにそれが発生すると、フレームワークはアクティビティ B を再開し、npe が発生します。

インスタンスが null の場合は、(アクティビティ B で) インスタンスを再作成する必要があります。

于 2012-06-07T23:15:44.540 に答える