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

Fragment中无法在onActivityResult控制Progressbar可见性的问题

解决Fragment中onActivityResult控制ProgressBar可见性无效的问题

你遇到的这个问题核心原因大概率是ProgressBar的引用失效了——当onActivityResult被调用时,你的Fragment视图可能已经经历了销毁重建(比如屏幕旋转、系统回收内存后重建),这时候你类级别声明的pbarVideoUpload指向的是已经被销毁的旧View,所以不管怎么调用setVisibility,都不会影响当前显示的视图。下面给你两种解决方案,从快速修复到更健壮的架构实现:

快速修复:每次操作时获取最新的ProgressBar引用

不要依赖类级别的pbarVideoUpload变量,而是在需要操作可见性的时候,通过当前Fragment的视图重新获取控件,确保操作的是当前活跃的View:

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data){ 
    if(requestCode == REQUEST_CODE_PROFILE_VIDEO_PATH){ 
        if(resultCode == Activity.RESULT_OK) { 
            String profileVideoPath = data.getExtras().getString(ProfileVideoRecordingActivity.VIDEO_PROFILE_PATH); 
            Log.d("DEBUG", profileVideoPath); 
            
            File profileVideo = new File(profileVideoPath); 
            if(profileVideo.exists()) { 
                // 先获取当前视图中的ProgressBar,确保引用有效
                View currentView = getView();
                if (currentView == null) {
                    Log.d("DEBUG", "Fragment视图已销毁,无法显示进度条");
                    return;
                }
                ProgressBar currentPbar = currentView.findViewById(R.id.pbarVideoUpload);
                currentPbar.setVisibility(View.VISIBLE);

                FireBaseWrapper fileUploader = new FireBaseWrapper(); 
                String serverFolderPath = "videoprofile"; 
                String contentType = "video/mp4"; 
                FireBaseAfterUpload afterUpload = new FireBaseAfterUpload() { 
                    @Override 
                    public void onSuccess(String uploadURL) { 
                        Log.d("DEBUG", "Successfully uploaded video to server"); 
                        Log.d("DEBUG", uploadURL); 
                        
                        // 异步回调中再次获取最新的ProgressBar,并切换到UI线程操作
                        if (isAdded() && getView() != null) {
                            getActivity().runOnUiThread(() -> {
                                ProgressBar callbackPbar = getView().findViewById(R.id.pbarVideoUpload);
                                callbackPbar.setVisibility(View.GONE);
                            });
                        }

                        // 后续ProfileService逻辑...
                    } 

                    @Override 
                    public void onProgress(String data) { } 

                    @Override 
                    public void onFaliure() { 
                        Log.d("DEBUG", "Error! Didn't upload"); 
                        if (isAdded() && getView() != null) {
                            getActivity().runOnUiThread(() -> {
                                ProgressBar callbackPbar = getView().findViewById(R.id.pbarVideoUpload);
                                callbackPbar.setVisibility(View.GONE);
                            });
                        }
                    } 
                }; 
                try { 
                    fileUploader.upload(profileVideo, profileVideo.getName(), serverFolderPath, afterUpload, contentType, false); 
                }catch (FileNotFoundException e){ 
                    Log.e("DEBUG", "FileNotFoundException", e); 
                    // 上传失败也要隐藏进度条
                    currentPbar.setVisibility(View.GONE);
                } 
            } 
        } 
    } 
}

这里要注意两个关键检查:

  • 操作View前先确认getView() != null和isAdded(),确保Fragment还附着在Activity上,视图处于活跃状态
  • 在Firebase的异步回调中,必须通过runOnUiThread切换到UI线程(部分第三方库回调可能自动在UI线程,但手动切换更保险)

更健壮的方案:用ViewModel管理上传状态

如果你的Fragment需要支持屏幕旋转等场景,推荐使用ViewModel来保存上传状态,这样视图重建后能自动恢复状态并更新UI,彻底避免View引用失效的问题:

  1. 创建一个ViewModel类,专门管理上传状态:
public class UploadViewModel extends ViewModel {
    private final MutableLiveData<Boolean> isUploading = new MutableLiveData<>(false);

    public void setUploading(boolean uploading) {
        isUploading.setValue(uploading);
    }

    public LiveData<Boolean> getIsUploading() {
        return isUploading;
    }
}
  1. 在你的Fragment中初始化ViewModel并观察状态:
private UploadViewModel uploadViewModel;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 初始化ViewModel,配置变化时不会被重建
    uploadViewModel = new ViewModelProvider(this).get(UploadViewModel.class);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.your_fragment_layout, container, false);
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ProgressBar pbarVideoUpload = view.findViewById(R.id.pbarVideoUpload);

    // 观察上传状态,自动更新ProgressBar可见性
    uploadViewModel.getIsUploading().observe(getViewLifecycleOwner(), uploading -> {
        pbarVideoUpload.setVisibility(uploading ? View.VISIBLE : View.GONE);
    });
}
  1. 在onActivityResult和Firebase回调中更新状态:
@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data){ 
    if(requestCode == REQUEST_CODE_PROFILE_VIDEO_PATH){ 
        if(resultCode == Activity.RESULT_OK) { 
            String profileVideoPath = data.getExtras().getString(ProfileVideoRecordingActivity.VIDEO_PROFILE_PATH); 
            Log.d("DEBUG", profileVideoPath); 
            
            File profileVideo = new File(profileVideoPath); 
            if(profileVideo.exists()) { 
                // 更新上传状态为开始
                uploadViewModel.setUploading(true);

                FireBaseWrapper fileUploader = new FireBaseWrapper(); 
                String serverFolderPath = "videoprofile"; 
                String contentType = "video/mp4"; 
                FireBaseAfterUpload afterUpload = new FireBaseAfterUpload() { 
                    @Override 
                    public void onSuccess(String uploadURL) { 
                        Log.d("DEBUG", "Successfully uploaded video to server"); 
                        Log.d("DEBUG", uploadURL); 
                        
                        // 上传完成,更新状态
                        uploadViewModel.setUploading(false);

                        // 后续ProfileService逻辑...
                    } 

                    @Override 
                    public void onProgress(String data) { } 

                    @Override 
                    public void onFaliure() { 
                        Log.d("DEBUG", "Error! Didn't upload"); 
                        // 上传失败,更新状态
                        uploadViewModel.setUploading(false);
                    } 
                }; 
                try { 
                    fileUploader.upload(profileVideo, profileVideo.getName(), serverFolderPath, afterUpload, contentType, false); 
                }catch (FileNotFoundException e){ 
                    Log.e("DEBUG", "FileNotFoundException", e); 
                    uploadViewModel.setUploading(false);
                } 
            } 
        } 
    } 
}

这种方式的优势在于,ViewModel会在Fragment的生命周期之外保留状态,即使视图被销毁重建,新的视图也会自动观察状态并更新ProgressBar,完全不需要手动管理View引用。

内容的提问来源于stack exchange,提问作者Chandan Pednekar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:39:55