Navigation Component跳转Fragment后ImageView图片消失是否正常?存ViewModel可行吗?
Hey there! Let's tackle your two questions step by step:
1. Is it normal that FragmentA's onDestroy isn't called when navigating to FragmentB?
Absolutely normal! Here's the breakdown:
When using the Android Navigation Component, navigating from FragmentA to FragmentB (via your actionGlobalBFragment action) keeps FragmentA in the back stack by default. This means FragmentA's core instance isn't destroyed—so onDestroy() won't execute. However, what does get triggered is onDestroyView(), because the Navigation Component automatically tears down the Fragment's view hierarchy when it's no longer visible on screen.
The reason your ImageView loses the image when returning to FragmentA is that when you come back, FragmentA re-runs onCreateView() to inflate a brand new view hierarchy. The fresh ImageView instance doesn't have the photo URI set anymore, since that configuration was only applied to the old view before onDestroyView() was called.
2. Is storing the image in ViewModel the right approach for persistent display?
Yes, this is a perfect use case for ViewModel!
ViewModel's lifecycle is designed to outlive Fragment view destruction and recreation—it survives onDestroyView()/onCreateView() cycles, which makes it ideal for holding data that needs to persist across navigation or configuration changes (like screen rotations).
Best practices to follow:
- Instead of storing the entire Bitmap (which can eat up memory quickly), store the
Uriof your photo file. This is far more efficient and avoids unnecessary memory overhead. - In FragmentA's
onCreateView()oronViewCreated(), retrieve the saved Uri from the ViewModel and re-apply it to the new ImageView instance. - Double-check that your
photoFilestill exists on device storage when you navigate back—avoid scenarios where the file gets deleted before returning to FragmentA.
Example implementation:
Step 1: Create a ViewModel class
import androidx.lifecycle.ViewModel class ImageViewModel : ViewModel() { var capturedPhotoUri: Uri? = null }
Step 2: Integrate the ViewModel in FragmentA
class FragmentA : Fragment() { private lateinit var imageViewModel: ImageViewModel private lateinit var photoImageView: ImageView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Initialize the ViewModel tied to this Fragment's lifecycle imageViewModel = ViewModelProvider(this)[ImageViewModel::class.java] } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_a, container, false) photoImageView = view.findViewById(R.id.photoImageView) // Restore the photo Uri from ViewModel when recreating the view imageViewModel.capturedPhotoUri?.let { uri -> photoImageView.setImageURI(uri) } return view } // When you finish capturing the photo: private fun handleCapturedPhoto(photoFile: File) { val imageUri = Uri.fromFile(photoFile) // Save the Uri to ViewModel first imageViewModel.capturedPhotoUri = imageUri // Then update the ImageView photoImageView.setImageURI(imageUri) } // Navigation logic remains unchanged private fun goToFragmentB() { val toFragmentB = AFragmentDirections.actionGlobalBFragment() findNavController().navigate(toFragmentB) } }
With this setup, when you navigate back to FragmentA, the onCreateView() method will pull the saved Uri from the ViewModel and re-apply it to the new ImageView—keeping your photo displayed without any issues.
内容的提问来源于stack exchange,提问作者Agung

