Android中setVisibility切换ProgressBar显示不生效问题
问题根本原因
你的代码核心错误是在UI主线程中调用thread.join(),直接阻塞了整个UI渲染流程,这是Android线程使用的典型误区。
按钮的点击回调默认运行在主线程(也就是负责所有UI绘制、事件响应的线程),你虽然先写了设置ProgressBar可见、ImageView隐藏的代码,但紧接着的thread.join()会让主线程一直卡住,等待你启动的工作线程执行完makeRequest()才会继续运行。
而Android的所有UI更新——包括你刚设置的visibility属性变更、ProgressBar本身的旋转动画绘制——都需要主线程空闲时,处理消息队列里的渲染任务才能生效。你直接把主线程堵死,前面设置的加载条显示逻辑根本没机会被渲染到屏幕上;等工作线程执行完,join()返回,你又立刻把ProgressBar设为隐藏、ImageView切回可见,整个过程UI完全没有机会刷新,自然看不到ProgressBar出现。
你加Thread.sleep()没有效果也是同样的原因:只要主线程被阻塞,不管等多久UI都不会更新,阻塞时间长了还会直接触发ANR(应用无响应)崩溃。
正确实现方式
Android中绝对不能在主线程做任何阻塞等待操作,工作线程执行完耗时任务(比如网络请求)后,必须切回主线程再执行UI更新,不要用join()等待线程。
最基础的原生实现写法如下:
searchBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ProgressBar progressBar = findViewById(R.id.progressBar); ImageView image = findViewById(R.id.image); // 先设置加载状态 image.setVisibility(View.INVISIBLE); progressBar.setVisibility(View.VISIBLE); // 启动子线程跑网络请求 new Thread(new Runnable() { @Override public void run() { makeRequest(); // 耗时网络请求 // 请求完成后,切回主线程更新UI runOnUiThread(new Runnable() { @Override public void run() { progressBar.setVisibility(View.INVISIBLE); image.setVisibility(View.VISIBLE); } }); } }).start(); } });
额外优化建议
- 你的布局中给ProgressBar的宽高、margin用了
sp单位是不规范的:sp是专门用于字体大小的单位,会随系统字体设置缩放,控件尺寸、间距应该统一用dp单位,避免不同设备上布局错乱。 - 所有UI相关操作必须在主线程执行,不要在子线程直接调用View的setVisibility等方法,否则会抛出
CalledFromWrongThreadException异常。 - 实际项目开发更推荐用协程、或者Retrofit/OkHttp这类网络框架自带的主线程回调能力,比手动创建Thread更稳妥,也能避免内存泄漏问题。
内容的提问来源于stack exchange,提问作者user17763934
相关产品推荐
相关产品推荐

