1

我有一个对象,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(); 
    }
}

异步任务

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);
    }
}
4

2 回答 2

1

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

您添加了一个回调,您需要在执行任务之前先设置它,然后在 AsyncTask 退出时触发它(doInBackground 完成并调用您的后执行)。

因此,从我在您的代码中看到的情况来看,构造函数不可能没有完成,并且您的对象会在回调中返回。

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

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

于 2013-02-17T03:05:51.217 回答
1

您可以在 AsyncTask 的 onPreExecute 方法上创建对象。因此,当调用 doInBackground 时,您的对象将已经创建。在这一点上,您可以调用该方法来创建 values

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);
    }
}
于 2013-02-17T05:48:11.607 回答