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