You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 03:12:15