使用AsyncTask的doInBackground()内的OkHttp库发出HTTP请求会阻止UI操作

Ani*_*tal 5 android okhttp

我正在尝试使用call.execute() - 同步调用在AsyncTask中发出OkHttp请求.

我的布局中有两个按钮.按下按钮1启动AsyncTask,执行OkHttp request.call.execute().

按下button2,我只更新一个TextView.

观察:当AsyncTask运行时,我无法更新TextView.

但是,如果我不使用AsyncTask并使用OkHttpClient.newCall().enqueue()方法,那么我可以通过按button2来更新TextView.

对于"为什么在这种情况下使用AsyncTask不起作用"的任何答案?

源代码示例:

bpost = (Button) findViewById(R.id.bpost);
    bpost.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            i++;
            tv.setText(""+i);
        }
    });


bstart.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

        OkHttpHandler handler = new OkHttpHandler();

            byte[] image = new byte[0];
            try {
                image = handler.execute(url).get();
                if (image != null && image.length > 0) {
                    Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
                    imageView.setImageBitmap(bitmap);
                    tv.setText("Total btytes download: " + image.length);
                }
            } catch (Exception e) {
                tv.setText("sorry, something went wrong!");
            }
        }


public class OkHttpHandler extends AsyncTask<String, Void, byte[]> {

    OkHttpClient client = new OkHttpClient();

    @Override
    protected byte[] doInBackground(String... params) {

        Request.Builder builder = new Request.Builder();
        builder.url(params[0]);
        Request request = builder.build();



        try {
            Response response = client.newCall(request).execute();
            return response.body().bytes();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

Pra*_*iya 10

这是因为get()方法AsyncTask等待计算在完成doInBackground方法,然后获取其结果.看到这个链接.

这将使您的主要UIThread处于等待模式,直到doInBackground完成执行或发生一些异常(即CancellationException,ExecutionExceptionInterruptedException).

你应该使用onPostExecute(Result)覆盖方法AsyncTask.

private class OkHttpHandler extends AsyncTask<String, Void, byte[]> {

        OkHttpClient client = new OkHttpClient();

        @Override
        protected byte[] doInBackground(String... params) {

            Request.Builder builder = new Request.Builder();
            builder.url(params[0]);
            Request request = builder.build();
            try {
                Response response = client.newCall(request).execute();
                return response.body().bytes();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(byte[] bytes) {
            super.onPostExecute(bytes);
            try {
                if (bytes != null && bytes.length > 0) {
                    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                    imageView.setImageBitmap(bitmap);
                    tv.setText("Total btytes download: " + bytes.length);
                }
            } catch (Exception e) {
                tv.setText("sorry, something went wrong!");
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)