AsyncTask仅在使用get()方法后返回值

时间:2013-04-11 15:35:27

标签: android android-asynctask

我已创建活动,用户点击按钮后应返回GeoPoint数组。执行http请求和解析答案的代码被提取到AsyncTask。在onPostExecute()方法中,我已使用overlayList方法返回的值指定了doInBackground(),但它无效并且

overlayList.size()  

发生NullPointerException。这是我的原始代码:

public class MyActivity extends Activity {

Button bt;
TextView tv1;
List<GeoPoint> overlayList;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    bt = (Button) findViewById(R.id.button);
    tv1 = (TextView) findViewById(R.id.textView);

    bt.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            String query = "http://maps.googleapis.com/maps/api/directions/json?origin=bla-bla&destination=bla-bla&sensor=false";

            Request mat =  new Request();
            mat.execute(query);

            if (overlayList.size() > 0){
                tv1.setText("List is OK!");
            }

        }
    });
}

private class Request extends AsyncTask<String, Void, ArrayList<GeoPoint>> {

    @Override
    protected ArrayList<GeoPoint> doInBackground(String... params) {
        return parse(connect(params[0]));
    }

    @Override
    protected void onPostExecute(ArrayList<GeoPoint> geoPoints) {
        super.onPostExecute(geoPoints);
        overlayList = geoPoints;
    }

    public JSONObject connect(String url) {
        ...    
    }

    public ArrayList<GeoPoint> parse(JSONObject jsonObject) {
        ...
    }

}

但如果我以这种方式修改我的OnClickListener

HttpRequest mat =  new HttpRequest();
mat.execute(query);

try {
    overlayList = mat.get();
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

一切正常,overlayList.size()返回列表大小。所以,我的问题 - 为什么onPostExecute()方法没有初始化我的列表?

1 个答案:

答案 0 :(得分:2)

AsyncTask正如其名称所暗示的那样 - 当doInBackground(...)中的代码继续运行时,onCreate(...)方法在单独的线程上异步运行。

在这里的代码中......

mat.execute(query);

if (overlayList.size() > 0){
    tv1.setText("List is OK!");
}

...致电if后,mat.execute(query)条件会立即检查 。换句话说,您的AsyncTask没有机会执行doInBackground(...)方法。

移动此代码......

if (overlayList.size() > 0){
    tv1.setText("List is OK!");
}

...进入onPostExecute(...)的{​​{1}}方法。

编辑:正如触发器在下面的注释中指出的那样,调用AsyncTask get()方法将阻塞主线程并等待返回结果。这有效地使用AsyncTask成为同步操作,在这种情况下使用AsyncTask毫无意义。

我能想到使用AsyncTask方法的唯一原因是来自主(UI)线程以外的线程,尽管我想不出有很多理由这样做。