Android Glide 4中downloadOnly的同步异步性及代码实现问询
Glide 4: downloadOnly.submit() 同步/异步问题详解
针对你提出的三个问题,结合Glide 4的API细节,我逐一解答如下:
问题1:上述代码执行是同步还是异步?
这段代码的执行是异步的。Glide.with(getContext()).downloadOnly().load(some_uri).submit()会返回一个FutureTarget<File>对象,调用submit()后,Glide会把下载任务提交到内部的后台线程池执行,当前调用线程(比如主线程)不会被阻塞,可以继续执行其他逻辑。只有当你主动调用FutureTarget.get()方法时,才会等待下载任务完成。
问题2:若为同步,如何将其改为异步执行?
虽然你的原始代码本身就是异步的,但假设你现在有一个同步阻塞的下载实现(比如直接在当前线程执行下载逻辑),要改成异步执行的话,推荐贴合Glide的设计方式来实现:
- 利用
FutureTarget的监听器机制,或者把下载任务交给Glide的异步流程,避免阻塞当前线程。示例代码如下:
// 提交异步下载任务 FutureTarget<File> futureTarget = Glide.with(getContext()) .downloadOnly() .load(some_uri) .submit(); // 添加监听器,异步回调下载结果 futureTarget.addListener(new RequestListener<File>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<File> target, boolean isFirstResource) { // 处理下载失败逻辑 Log.e("GlideDownload", "Download failed", e); return false; } @Override public boolean onResourceReady(File resource, Object model, Target<File> target, DataSource dataSource, boolean isFirstResource) { // 下载完成,处理已下载的文件 Log.d("GlideDownload", "File downloaded to: " + resource.getAbsolutePath()); return false; } });
你也可以用Java的CompletableFuture或者Kotlin协程来封装异步逻辑,让代码更简洁。
问题3:若为异步,如何将其改为同步执行?
因为原始代码是异步的,要改成同步执行,核心是调用FutureTarget.get()方法阻塞当前线程,直到下载完成。重要提醒:绝对不能在主线程调用get(),否则会触发ANR(应用无响应),必须在后台线程执行。
Java 实现示例(使用线程池):
// 创建后台线程池 ExecutorService downloadExecutor = Executors.newSingleThreadExecutor(); downloadExecutor.execute(() -> { try { FutureTarget<File> futureTarget = Glide.with(getContext()) .downloadOnly() .load(some_uri) .submit(); // 阻塞当前线程,直到下载完成或超时 File downloadedFile = futureTarget.get(30, TimeUnit.SECONDS); // 处理下载后的文件 Log.d("GlideDownload", "Synced file path: " + downloadedFile.getAbsolutePath()); } catch (InterruptedException | ExecutionException | TimeoutException e) { e.printStackTrace(); // 处理下载异常或超时 } }); // 记得在合适的时机关闭线程池(比如页面销毁时) // downloadExecutor.shutdown();
Kotlin 实现示例(使用协程):
// 在IO线程执行同步下载 lifecycleScope.launch(Dispatchers.IO) { try { val futureTarget = Glide.with(context) .downloadOnly() .load(some_uri) .submit() val downloadedFile = futureTarget.get() // 处理下载完成的文件 Log.d("GlideDownload", "Synced file path: ${downloadedFile.absolutePath}") } catch (e: Exception) { e.printStackTrace() // 处理异常 } }
使用get(long timeout, TimeUnit unit)还可以设置超时时间,避免线程无限阻塞。
内容的提问来源于stack exchange,提问作者AlanSTACK
相关产品推荐
相关产品推荐

