AsyncTask不等待在完成之前创建对象

时间:2013-02-17 01:47:30

标签: android android-asynctask

我有一个对象MyObject,它用一些随机数填充自己。它不需要很长时间,看似很快。但是,这些值在UI上使用,有时在构建UI时它还没有完全准备好。

我创建了一个用于实例化对象的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进行部分计算,如果这会导致竞争条件。

以下是使用MyFragment中的任务的示例methodCall()

问题我如何等待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);
    }
}

2 个答案:

答案 0 :(得分:1)

如果在创建对象时没有在对象内部创建任何新线程,那么您所做的事情应该完全正常。

你已经添加了一个回调,你需要在执行任务之前先设置它,然后当AsyncTask退出时(DoInBackground完成并调用你的post执行)它将被触发。

因此,从我在代码中看到的内容,构造函数无法完成,并且您的对象将在回调中返回。

因此,检查是否有可能在createValues方法中的对象中抛出异常。

您是否有发生异常的堆栈跟踪?

答案 1 :(得分: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);
    }
}