Android中如何在AsyncTask中展示自定义ProgressBar
问题原因
- 构造参数错误:
ProgressBar构造函数的第四个参数接收的是样式资源ID,你传入的是布局文件ID,完全无法加载你定义的包含进度条和文本的自定义布局。 - 视图类型不匹配:你定义的
custom_progress_bar.xml根布局是ConstraintLayout,不是ProgressBar,用ProgressBar类型接收加载结果本身就会失效。 - 布局参数缺少约束:你创建的
ConstraintLayout.LayoutParams没有添加任何父布局约束,就算视图加载成功也不会出现在可见区域。
修复方案
修改 AsyncTask 相关代码,正确加载、添加自定义进度布局:
// 把原来的ProgressBar类型变量改为View类型,对应整个自定义布局 View progressLayout; // 给AsyncTask指定泛型,第二个参数为进度值类型 public class LoadData extends AsyncTask<Void, Integer, Object> { @Override protected void onPreExecute() { super.onPreExecute(); // 避免重复添加布局 if (progressLayout != null && progressLayout.getParent() != null) { return; } // 加载自定义进度布局 LayoutInflater inflater = LayoutInflater.from(MyActivity.this); progressLayout = inflater.inflate(R.layout.custom_progress_bar, null); ConstraintLayout rootCl = findViewById(R.id.constraintLayout); ConstraintLayout.LayoutParams lp = new ConstraintLayout.LayoutParams( ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT ); // 添加约束让布局铺满父布局,内部进度条会自动居中 lp.topToTop = ConstraintLayout.LayoutParams.PARENT_ID; lp.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID; lp.startToStart = ConstraintLayout.LayoutParams.PARENT_ID; lp.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID; progressLayout.setLayoutParams(lp); // 添加到根布局末尾,默认在Z轴最顶层 rootCl.addView(progressLayout); } @Override protected Object doInBackground(Void... voids) { // 加载数据过程中如果要更新进度,调用publishProgress方法传入进度值 // 例如加载到50%时:publishProgress(50); return null; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); if (progressLayout == null) return; int currentProgress = values[0]; // 更新进度条和文本 ProgressBar customBar = progressLayout.findViewById(R.id.customProgressBar); TextView progressText = progressLayout.findViewById(R.id.textViewProgress); customBar.setProgress(currentProgress); progressText.setText(currentProgress + " %"); } @Override protected void onPostExecute(Object o) { // 任务结束后直接移除布局,避免残留 if (progressLayout != null && progressLayout.getParent() != null) { ((ViewGroup) progressLayout.getParent()).removeView(progressLayout); progressLayout = null; } } }
补充说明
- 注意不要多次执行同一个
AsyncTask实例,每次发起加载需要新建LoadData实例调用execute()方法。 - 官方已废弃
AsyncTask,长期来看推荐使用协程、WorkManager或者ThreadPoolExecutor替代异步任务实现。
内容的提问来源于stack exchange,提问作者MDNick2000
相关产品推荐
相关产品推荐

