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引用失效的问题:
- 创建一个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; } }
- 在你的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); }); }
- 在
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
相关产品推荐
相关产品推荐

