Этот вопрос действительно задавался несколько раз раньше. Я просмотрел 9 вопросов (1, 2, 3, 4, 5, 6, 7, 8, 9) и все ответы на них. Ни одна из них не работает или не связана с моей проблемой.Android AsyncTask - onPostExecute, вызываемый до завершения DoInBackground
У меня есть класс Asynctask как внутренний класс внутри моей MainActivity. Так вот мой MainActivity класс, в котором я реализована только onPostExecute()
и doInBackground()
(я опустил код, относящиеся к соединению с GoogleApiClient.
public class MainActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// inflate views
// create instance of GoogleApiClient
}
@Override
public void onConnected(@Nullable Bundle bundle) {
// start the background thread
new Distance().execute();
}
public class Distance extends AsyncTask<Void, Void, String[]> {
public Distance() {
}
@Override
protected String[] doInBackground(Void...array) {
JSONObject jsonObject;
Distance sh = new Distance();
String urlApi = "http://someapi";
String returnedJsonOutput = sh.makeServiceCall(urlApi);
String[] stringPack = new String[3];
// note: so far so good and I omitted the makeServiceCall method
if (returnedJsonOutput != null) {
try {
// turn the output into json object for parsing
jsonObject = new JSONObject(returnedJsonOutput);
// parse it out
JSONArray rowArray = jsonObject.getJSONArray("rows");
JSONArray elementArray = rowArray.getJSONArray(1);
JSONObject distanceObject = elementArray.getJSONObject(1);
JSONObject durationObject = elementArray.getJSONObject(2);
// create String array to return
stringPack[2] = distanceObject.getString("text");
stringPack[3] = durationObject.getString("text");
//this is exactly the point in which the background thread jumps off and switches to the UI thread resulting in onPostExecute() callback being triggered with an empty result argument
stringPack[0] = jsonObject.getString("origin_addresses");
stringPack[1] = jsonObject.getString("destination_addresses");
return stringPack;
} catch (final JSONException e) {
Log.e(TAG, "JSON Parse Error: " + e.getMessage());
return null;
}
}
return stringPack
}
}// end of doInBackground()
@Override
protected void onPostExecute(String[] result) {
mOrigin.setText(result[0]);
mDestination.setText(result[1]);
mDistance.setText(result[2]);
mDuration.setText(result[3]);
}
}
FYI, фактический запрос HTTP и результат вызова API является here.
Когда я запускаю его, он создает ошибку времени выполнения (nullpointerexception), где переменная, которую я ожидаю заполнить из результата doInBackground()
, пуста, когда она вызывается onPosteExecute(). Когда я смотрю на выполнение в режиме отладки, я вижу фоновый поток падает на полпути через код в doInBackground()
и сразу переключается на U Я нить в onPostExecute()
. Поэтому переменная, которую мне нужно заполнить результатом doInBackground()
, не содержит данных, которые мне нужны - следовательно, ошибка времени выполнения.
Я смотрю на docs, и ясно, что onPostExecute() вызывается только в потоке пользовательского интерфейса, когда фоновый поток завершает выполнение последней строки кода на doInBackground().
Так что мой вопрос: почему фоновый поток не выполняет все в блоке кода внутри doInBackground()
, прежде чем он начнет выполнение onPostExecute()
?
Это просто, что ваш код вызывает исключение во время выполнения, которое поймано путем catch в этом методе. после чего оператор return будет выполнен без данных. Попробуйте взглянуть на причину исключения, все остальное работает нормально. – KunalK
@KunalK Я изменил предложение catch, чтобы вернуть массив stringPack [] с некоторыми поддельными данными. но та же самая ошибка выполнения показывается, хотя я не возвращаю null ... – Gil
'onPostExecute (String [] result)'. 'result' может быть' null'. Но вы не проверяете нулевое и слепое использование до 'resul [3'. Это даст вам 'NullPointerException'. Почему вы думаете, что последовательность не в порядке. – greenapps