当 AsyncTask 完成时返回一个值

Posted

技术标签:

【中文标题】当 AsyncTask 完成时返回一个值【英文标题】:Returning a value when an AsyncTask has finished 【发布时间】: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... 它已经有回调函数 【参考方案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.

【讨论】:

以上是关于当 AsyncTask 完成时返回一个值的主要内容,如果未能解决你的问题,请参考以下文章

C# Async Await 注意事项

获得致命异常:使用 Async 类的 AsyncTask #1

Android AsyncTask在完成工作后返回值

AsyncTask Android - 设计模式和返回值

android AsyncTask 怎么返回值给UI线程

Async Json 提要晚于 AsyncTask 完成以从 sqlite DB 加载数据。如何同步它们或更好的解决方案?