2013-04-11 62 views
0

我已经创建了活动,应该在用户单击按钮后返回GeoPoint数组。执行http请求和解析答案的代码被提取到AsyncTask。在onPostExecute()方法我已经分配overlayListdoInBackground()方法的返回值,但它没有工作,AsyncTask仅在使用get()方法后返回值

overlayList.size() 

thows一个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()方法不初始化我的列表?

+0

overlayList.add(geoPoints); – Raghunandan 2013-04-11 15:37:29

+0

不要调用'super.onPostExecute(geoPoints);'。 – 2013-04-11 15:38:53

+0

可以发表你的解析(连接(...))代码 – Raghunandan 2013-04-11 15:42:15

回答

2

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

在你的代码在这里...

mat.execute(query); 

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

...你叫mat.execute(query)if条件立即检查。换句话说,你的AsyncTask还没有机会执行它的doInBackground(...)方法。

移动这个代码...

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

...到您的AsyncTaskonPostExecute(...)方法。

编辑:由于triggers在下面的注释中指出,调用AsyncTaskget()方法会阻塞主线程并等待返回结果。这有效地使得使用AsyncTask成为同步操作,在这种情况下,使用AsyncTask没有意义。

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

+2

除了上述原因,第二种发布方式的原因是因为在AsyncTask上调用'get()'方法会导致它阻塞主线程,直到任务完成。 – triggs 2013-04-11 15:50:23

+0

@triggs:同意,我应该指出这一点。 – Squonk 2013-04-11 15:52:38