2017-02-02 4 views
-2

Этот вопрос действительно задавался несколько раз раньше. Я просмотрел 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()?

+2

Это просто, что ваш код вызывает исключение во время выполнения, которое поймано путем catch в этом методе. после чего оператор return будет выполнен без данных. Попробуйте взглянуть на причину исключения, все остальное работает нормально. – KunalK

+0

@KunalK Я изменил предложение catch, чтобы вернуть массив stringPack [] с некоторыми поддельными данными. но та же самая ошибка выполнения показывается, хотя я не возвращаю null ... – Gil

+0

'onPostExecute (String [] result)'. 'result' может быть' null'. Но вы не проверяете нулевое и слепое использование до 'resul [3'. Это даст вам 'NullPointerException'. Почему вы думаете, что последовательность не в порядке. – greenapps

ответ

1

Если ваш код завершился нормально без ошибок, он вернет пустой массив (размером 3), который вы конкретно определяете ранее.

Ваш блок Catch возвращает null, поэтому весьма вероятно, что произошла ошибка, которую вы ловушки, а затем обрабатываете, возвращая null.

Поместите контрольную точку в свой Catch bloack и исследуйте причину исключения.