AsyncTask returns a value only after using the get () method

I created an activity that should return a GeoPoint array after the user clicks a button. The code that executes the HTTP request and the syntax response is retrieved in AsyncTask. In the onPostExecute() method, I assigned an overlayList with the value returned by the doInBackground() method, but this did not work and

 overlayList.size() 

throws a NullPointerException. Here is my original code:

 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) { ... } } 

But if I change my OnClickListener this way:

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

everything goes fine and overlayList.size() returns the size of the list. So my question is: why doesn't the onPostExecute() method initialize my list?

0
source share
1 answer

An AsyncTask does what it calls - the doInBackground(...) method runs asynchronously in a separate thread while the code in onCreate(...) continues to work.

In your code here ...

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

... the if condition if checked immediately after calling mat.execute(query) . In other words, your AsyncTask not able to execute its doInBackground(...) .

Move this code ...

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

... to the onPostExecute(...) method of your AsyncTask .

EDITING. As pointed out in the comments below, calling the get() AsyncTask blocks the main thread and waits for the result to return. This effectively makes the use of AsyncTask synchronous, in which case it makes no sense to use AsyncTask .

The only reason I can use the get() method will be from a thread other than the main (UI) thread, although I cannot think of many reasons for this.

+2
source

Source: https://habr.com/ru/post/949247/


All Articles