当 AsyncTask 完成时返回一个值
Posted
技术标签:
【中文标题】当 AsyncTask 完成时返回一个值【英文标题】:Returning a value when an AsyncTask has finished 【发布时间】:2018-08-30 19:25:57 【问题描述】:我知道我可以在执行任务的同时使用接口作为委托来做事,我也知道我可以使用get()
使 AsyncTask 同步,但我不想阻塞 UI 线程。
我使用AsyncTask
和OkHttp
上传文件并得到如下结果:
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 完成时返回一个值的主要内容,如果未能解决你的问题,请参考以下文章
获得致命异常:使用 Async 类的 AsyncTask #1
Async Json 提要晚于 AsyncTask 完成以从 sqlite DB 加载数据。如何同步它们或更好的解决方案?