如何使用AsyncTask在PDF加载前实现实时水平内容加载进度条
实现带实时进度的PDF加载进度条方案
第一步:添加水平进度条布局
在你的页面XML布局中添加对应进度条控件:
<ProgressBar android:id="@+id/contentLoadingProgressBar" style="@style/Widget.AppCompat.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="100" android:progress="0" android:visibility="VISIBLE" />
第二步:修改AsyncTask实现进度监听
你需要将原AsyncTask的泛型参数调整为<String, Integer, InputStream>,第二个Integer参数用于传递进度值,完整修改后代码如下:
class RetrievePDFStream extends AsyncTask<String, Integer, InputStream> { private ProgressBar progressBar; // 构造方法传入进度条实例,若为Activity内部类可直接访问成员变量省略该步骤 public RetrievePDFStream(ProgressBar progressBar) { this.progressBar = progressBar; } @Override protected void onPreExecute() { super.onPreExecute(); // 加载前重置进度,显示进度条 progressBar.setProgress(0); progressBar.setVisibility(View.VISIBLE); } @Override protected InputStream doInBackground(String... strings) { InputStream inputStream = null; ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { URL urlx = new URL(strings[0]); HttpURLConnection urlConnection = (HttpURLConnection) urlx.openConnection(); if (urlConnection.getResponseCode() == 200) { inputStream = new BufferedInputStream(urlConnection.getInputStream()); // 获取PDF文件总大小 int totalLength = urlConnection.getContentLength(); byte[] buffer = new byte[1024]; int readBytes; int currentBytes = 0; // 边读取边计算实时进度 while ((readBytes = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, readBytes); currentBytes += readBytes; // 仅在能拿到总大小的情况计算进度 if (totalLength > 0) { int progress = (int) ((currentBytes * 100) / totalLength); publishProgress(progress); } } return new ByteArrayInputStream(outputStream.toByteArray()); } } catch (IOException e) { e.printStackTrace(); return null; } finally { // 资源回收 try { if (inputStream != null) inputStream.close(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); // 更新进度条显示 progressBar.setProgress(values[0]); } @Override protected void onPostExecute(InputStream inputStream) { // 加载完成隐藏进度条 progressBar.setVisibility(View.GONE); if (inputStream != null) { pdfView.fromStream(inputStream).load(); } else { Toast.makeText(progressBar.getContext(), "PDF加载失败,请检查网络或文件地址", Toast.LENGTH_SHORT).show(); } } }
第三步:调用执行
在需要触发PDF加载的位置传入进度条实例执行任务即可:
ProgressBar loadingBar = findViewById(R.id.contentLoadingProgressBar); new RetrievePDFStream(loadingBar).execute("你要加载的PDF文件URL地址");
补充说明
- 如果服务端没有返回
Content-Length响应头,会拿不到文件总大小,此时可以将进度条设置为不确定模式progressBar.setIndeterminate(true)即可 - AsyncTask从Android 11(API 30)开始被标记为废弃,如果你面向新版本开发,可以替换为Kotlin协程、AsyncTaskLoader或者WorkManager实现相同效果
内容的提问来源于stack exchange,提问作者Anil Kumhar
相关产品推荐
相关产品推荐

