Android AsyncTask - 在doInBackground完成之前调用的onPostExecute

时间:2017-02-02 12:13:49

标签: java android multithreading android-asynctask

这个问题实际上曾多次被问过。我查看了9个问题(1234567,{ {3}},8)及其所有答案。它们都不起作用或与我的问题有关。

我将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]);
    }
}

仅供参考,实际的http请求和API调用的结果为9

当我运行它时,它会产生一个运行时错误(nullpointerexception),当调用onPosteExecute()时,我期望从doInBackground()的结果填充的变量为空。当我在调试模式下查看执行时,我看到后台线程在doInBackground()中的代码中途脱落并立即切换到onPostExecute()中的UI线程。所以我需要用doInBackground()的结果填充的变量不包含我需要的数据 - 因此运行时错误。

我查看here,很明显只有后台线程在doInBackground()上执行最后一行代码时,才会在UI线程上调用onPostExecute()。

所以我的问题是:为什么后台线程在开始执行doInBackground()之前没有在onPostExecute()内的代码块中执行所有内容?

1 个答案:

答案 0 :(得分:1)

如果您的代码正常完成且没有错误,它将返回您之前明确定义的空数组(大小为3)。

您的Catch块返回null,因此很可能发生错误,您可以通过返回null来捕获然后处理。

在Catch bloack中放置一个断点并调查异常原因。