【问题标题】:Returning a value when an AsyncTask has finished当 AsyncTask 完成时返回一个值
【发布时间】:2018-08-30 19:25:57
【问题描述】:

我知道我可以在执行任务的同时使用接口作为委托来做事,我也知道我可以使用get() 使 AsyncTask 同步,但我不想阻塞 UI 线程。

我使用AsyncTaskOkHttp 上传文件并得到如下结果:

static class UploadFile extends AsyncTask<Void, Void, String> {

    private TaskInterface<String, Float> delegate = null;

    private String url;
    private File file;
    private MediaType fileType;

    private String ret = "NULL";

    UploadFile(String url, File file, MediaType fileType, TaskInterface<String, Float> delegate){
        this.delegate = delegate;
        this.url = url;
        this.file = file;
        this.fileType = fileType;
    }

    @Override
    protected void onPreExecute() {
        if (delegate != null){
            delegate.onPreCompleteTask();
            Log.d("UPLOADING:", "File : " + file.getName());
        }
    }

    @Override
    protected String doInBackground(Void...voids) {

            RequestBody body = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("upload", file.getName(),RequestBody.create(fileType, file))
                    .build();

            Request request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .build();
            try {
                Response response = okhttpclient.newCall(request).execute();
                ret = response.body().string();
            } catch (Exception e){
                e.printStackTrace();
                Log.e("HttpClient", "Upload: " + e.getMessage());
            }

        return ret;
    }

    @Override
    protected void onPostExecute(String result) {
        if (delegate != null){
            delegate.onCompleteTask(result);
            Log.d("ON UPLOAD POST EXECUTE", result);
        }
    }
}

然后我用这样的方法创建任务:

Boolean validateVCode(File file){

    final boolean[] boolResult = new boolean[1];

            new UploadFile("http://localhost/doThings.php",
                        file,
                        myMediaType,
                        new TaskInterface<String, Float>() {
                            @Override
                            public void onPreCompleteTask(){
                                processDialog.show();
                            }

                            @Override
                            public void onCompleteTask(String result) {
                                processDialog.dismiss();
                                boolResult[0] = result.contains("true");
                            }
                        }).execute();

    return boolResult[0];
}

但问题是任务在后台被抛出并且方法继续工作,所以在方法的第一次执行中它返回 boolResult[0] 的默认值是 false,但在第二次执行中(之后任务完成)它将返回值更改为任务的结果。因此需要执行两次方法才能获得所需的值。

有什么变通方法可以让方法在不阻塞主线程的情况下等待任务?

【问题讨论】:

  • 你不能阻止一个方法而不阻塞它正在运行的线程。所有的库,包括 SDK 本身,都因此使用监听器模式。
  • 感谢您的澄清。那么,我可以创建一个不同的线程并在不影响性能的情况下阻止它吗?
  • 主线程没有性能损失? - 是的
  • 虽然我不建议在android上创建自己的线程
  • 你不需要 AsyncTask 来使用 OkHTTP... 它已经有回调函数

标签: java android asynchronous interface android-asynctask


【解决方案1】:

如果您不想阻塞 UI 线程,那么您必须让工作并行完成。在这种情况下,无法从 UI 线程返回结果。

那里是您的主要问题

是否有任何解决方法可以使方法等待任务而不 阻塞主线程?

本身没有任何意义。

解决方案

  • 使过滤器成为无效方法。
  • 包装你想用 生成另一个方法 (onResult(boolean result)) 并从 onCompleteTask() 调用它。
  • 做任何事 你想在那里做。

【讨论】:

  • 您的解决方案有问题。最后一个方法返回一个布尔值,我需要检查一些东西,以便我这样调用它: if (validateVCode(someFile)) { doSomeWork(); }
  • 只要把它称为 validateVCode(someFile) onResult(boolean result){if(result){doSomeWork();}} 这就是我要告诉你的。
  • 问题仍然存在,直到 AsyncTask 完成它的工作才设置结果。
  • 就像现实生活中一个动作完成之前不可能有结果一样,在任务完成之前你也无法得到结果。
  • 是的,它被部分接受了,我把它放在第一位,但它并不能解决所有问题,所以我在网上搜索了另一个解决方案。这是 RxJava。非常感谢您的支持。
【解决方案2】:

我认为我找到了两个解决问题的方法:

  • 调用“onCompleteTask(String result)”中的检查方法:

    @Override public void onCompleteTask(String result){ processDialog.dismiss(); checkingMethod(result.contains("true")); }

  • 实现 RxJava: 解释here.

【讨论】:

    猜你喜欢
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    相关资源
    最近更新 更多