在AsyncTask的doInBackground()方法中使用OkHttp库进行HTTP请求会阻塞UI操作。

6

我试图使用call.execute()在AsyncTask中进行OkHttp请求 -- 同步调用。

我的布局中有两个按钮。按下button1会启动AsyncTask,然后执行OkHttp请求的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;
    }
}

我没有在任何地方使用Thread.sleep()或wait()。 - Anish Mittal
你能分享一些代码吗? - M4R1KU
@M4R1KU:现在查看源代码。 - Anish Mittal
@jankigadhiya:现在查看源代码。 - Anish Mittal
@jankigadhiya:已发布相关代码。 - Anish Mittal
@jankigadhiya:不,我只想一直按下按钮bpost,我的TextView应该更新为一个新值。但是,除非AsyncTask完成,否则不会发生这种情况。 - Anish Mittal
1个回答

11

这是因为 AsyncTaskget() 方法会等待计算在 doInBackground 方法中完成,然后检索其结果。请参见此 链接

这将使您的主要 UIThread 处于等待模式,直到 doInBackground 完成其执行或出现异常(即 CancellationExceptionExecutionExceptionInterruptedException)。

您应该使用 AsyncTaskonPostExecute(Result) 覆盖方法。

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!");
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接