2013-02-17 98 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); 
    } 
}