2013-02-17 95 views
1

我有一個對象,MyObject,用一些隨機數填充自己。這不需要很長時間,看起來是瞬間的。但是,這些值在用戶界面上使用,有時在構建用戶界面時還沒有完全準備好。AsyncTask沒有等待完成之前創建的對象

我創建了一個用於實例化對象的AsyncTask,它在本文後面。

但是doInBackground(...)在以這種方式調用onPostExecute(...)之前沒有完全實例化對象。

protected MyObject doInBackground(Void... unused) { 
    // this may take a few moments and cause a null reference 
    // so make a task 
    MyObject obj = new MyObject(); 
    return obj; 
} 

我也試着用一個標誌來表示完成,但它似乎也不能保證。

MyObject obj = new MyObject(); 
while (obj.isComplete() == false) { 
    // do nothing. Wait for completion 
} 

return obj; 

裏面的MyObject簡單

public MyObject() { 
    createValues(); // entire object created with this 
    this.mComplete = true; 
} 

它失敗少,但仍然沒有。 createValues()使用ArrayList作爲其計算的一部分,如果這是造成競爭條件。

下面是使用methodCall()中的任務的示例MyFragment

問題我該如何等待,直到MyObject完全實例化爲止?

堆棧跟蹤

java.lang.NullPointerException 
    at MyFragment.setupFragment(MyFragment.java:95) 
    at MyFragment.onTaskComplete(MyFragment.java:143) 
    at MyTask.onPostExecute(MyTask.java:37) 
    at MyTask.onPostExecute(MyTask.java:1) 
    at android.os.AsyncTask.finish(AsyncTask.java:631) 

片段

public class MyFragment extends Fragment implements MyTask.OnTaskComplete { 
    private MyObject mMyObject; 

    // ... 

    public void methodCall() { 
     // generate puzzle and set it up in the background 
     MyTask task = new MyTask(this); 
     task.execute(); 
    } 

    function void setupFragment() { 
      // null pointer exception here 
      // mMyObject is not initiated yet and only some times 
      // values is an array of integers 
     int example = this.mMyObject.values[0]; 
    } 

    @Override 
    public void onTaskComplete(MyObject obj) { 
     // returned from MyTask 
     this.mMyObject = obj; 
     this.setupFragment(); 
    } 
} 

的AsyncTask

public class MyObjectTask extends AsyncTask<Void, Void, MyObject> { 
    public static interface OnTaskComplete { 
     public abstract void onTaskComplete(MyObject obj); 
    } 
    static final String TAG = "MyObjectTask"; 

    private OnTaskComplete mListener; 

    public MyObjectTask(OnTaskComplete listener) { 
     this.mListener = listener; 
    } 

    @Override 
    protected MyObject doInBackground(Void... unused) { 
     // this may take a few moments and cause a null reference 
     // so make a task 
     return new MyObject(); 
    } 

    @Override 
    protected void onPostExecute(MyObject obj) { 
     this.mListener.onTaskComplete(obj); 
    } 
} 
+0

'mListener'可以'null' – Geros 2013-02-17 02:13:04

+0

好點。我會確保捕獲那個 – Kirk 2013-02-17 02:27:15

回答

1

你正在做什麼都要如果您在創建對象時沒有創建任何新線程,則完全沒問題。

您已經添加了一個回調,在執行任務之前您需要先設置一個回調,然後當AsyncTask退出(doInBackground結束並且您的帖子執行被調用)時它將被觸發。

所以從我在代碼中看到的是沒有辦法構造函數沒有完成,你的對象在回調中返回。

因此,檢查是否可能在方法createValues中的對象中引發異常。

你有發生異常的堆棧跟蹤嗎?

+0

謝謝你的答案。我已經將該任務的用法添加到了該文章中,並在'setupFragment()'方法中獲得了一個空指針。我已經添加了相關的堆棧跟蹤。 – Kirk 2013-02-17 04:03:41

+0

我只是想,如果在線程中導致問題,我在'MyObject'內部使用'ArrayList'。我現在正在研究這個問題。 – Kirk 2013-02-17 04:31:55

+0

你的對象沒有被聲明爲一個數組,但你仍然像這樣訪問它。我認爲這個問題是在你如何在我的對象中設置事物的地方。一切看起來都很好。如果您使用的是數組列表,則需要將值作爲list.get(position)。你現在的方式就像一個普通的數組而不是一個ArrayList,因爲你的狀態爲 – DArkO 2013-02-17 04:34:36

1

您可以在AsyncTask的onPreExecute方法上創建對象。所以,當doInBackground被調用時,你的對象已經被創建了。在這一點上,您只需撥打即可創建值

public class MyObjectTask extends AsyncTask<Void, Void, MyObject> { 
    public static interface OnTaskComplete { 
     public abstract void onTaskComplete(MyObject obj); 
    } 

    static final String TAG = "MyObjectTask"; 

    private OnTaskComplete mListener; 
    private MyObject myObject; 

    public MyObjectTask(OnTaskComplete listener) { 
     this.mListener = listener; 
    } 

    @Override 
    protected void onPreExecute() { 
     myObject = new MyObject(); 
    } 

    @Override 
    protected MyObject doInBackground(Void... unused) { 
     // this may take a few moments and cause a null reference 
     // so make a task 
     myObject.createValues(); 
     return myObject; 
    } 

    @Override 
    protected void onPostExecute(MyObject obj) { 
     this.mListener.onTaskComplete(obj); 
    } 
}