Các API ViewModel Scoping Một phần của Android Jetpack.
Phạm vi là yếu tố then chốt để sử dụng ViewModel một cách hiệu quả. Mỗi ViewModel sẽ thuộc một phạm vi đối tượng triển khai giao diện ViewModelStoreOwner
. Có một số API giúp bạn dễ dàng quản lý phạm vi của ViewModel.
Tài liệu này nêu ra một số kỹ thuật chính mà bạn nên biết.
Phương thức ViewModelProvider.get()
cho phép bạn có được thực thể của một ViewModel thuộc phạm vi của ViewModelStoreOwner
bất kỳ. Người dùng Kotlin có các hàm mở rộng khác nhau dành cho trường hợp sử dụng phổ biến nhất. Về bản chất, tất cả các phương thức triển khai hàm mở rộng Kotlin đều sử dụng API ViewModelProvider.
ViewModel thuộc phạm vi của ViewModelStoreOwner gần nhất
Bạn có thể thiết lập phạm vi của ViewModel trong một Hoạt động, Mảnh hoặc đích đến của biểu đồ Điều hướng. Với các hàm mở rộng viewModels()
do thư viện Hoạt động, Mảnh và Điều hướng cung cấp cũng như hàm viewModel()
trong Compose, bạn có thể xem một thực thể của ViewModel thuộc phạm vi của ViewModelStoreOwner
gần nhất.
Khung hiển thị
import androidx.activity.viewModels class MyActivity : AppCompatActivity() { // ViewModel API available in activity.activity-ktx // The ViewModel is scoped to `this` Activity val viewModel: MyViewModel by viewModels() } import androidx.fragment.app.viewModels class MyFragment : Fragment() { // ViewModel API available in fragment.fragment-ktx // The ViewModel is scoped to `this` Fragment val viewModel: MyViewModel by viewModels() }
Thành phần hiển thị
import androidx.lifecycle.ViewModelProvider; public class MyActivity extends AppCompatActivity { // The ViewModel is scoped to `this` Activity MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class); } public class MyFragment extends Fragment { // The ViewModel is scoped to `this` Fragment MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class); }
Compose
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( modifier: Modifier = Modifier, // ViewModel API available in lifecycle.lifecycle-viewmodel-compose // The ViewModel is scoped to the closest ViewModelStoreOwner provided // via the LocalViewModelStoreOwner CompositionLocal. In order of proximity, // this could be the destination of a Navigation graph, the host Fragment, // or the host Activity. viewModel: MyViewModel = viewModel() ) { /* ... */ }
ViewModel thuộc phạm vi của ViewModelStoreOwner bất kỳ
Hàm ComponentActivity.viewModels()
và Fragment.viewModels()
trong hệ thống Khung hiển thị và hàm viewModel()
trong Compose sẽ lấy một tham số ownerProducer
(không bắt buộc) mà bạn có thể sử dụng để chỉ định ViewModelStoreOwner
nào mà thực thể của ViewModel nằm trong đó.
Mẫu sau đây cho biết cách lấy một thực thể của ViewModel thuộc phạm vi của mảnh mẹ:
Số lượt xem
import androidx.fragment.app.viewModels class MyFragment : Fragment() { // ViewModel API available in fragment.fragment-ktx // The ViewModel is scoped to the parent of `this` Fragment val viewModel: SharedViewModel by viewModels( ownerProducer = { requireParentFragment() } ) }
Thành phần hiển thị
import androidx.lifecycle.ViewModelProvider; public class MyFragment extends Fragment { SharedViewModel viewModel; @Override public void onViewCreated(View view, Bundle savedInstanceState) { // The ViewModel is scoped to the parent of `this` Fragment viewModel = new ViewModelProvider(requireParentFragment()) .get(SharedViewModel.class); } }
Compose
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( context: Context = LocalContext.current, // ViewModel API available in lifecycle.lifecycle-viewmodel-compose // The ViewModel is scoped to the parent of the host Fragment // where this composable function is called viewModel: SharedViewModel = viewModel( viewModelStoreOwner = (context as Fragment).requireParentFragment() ) ) { /* ... */ }
Vì việc lấy ViewModel thuộc phạm vi của Hoạt động từ một Mảnh là một trường hợp sử dụng phổ biến. Thời gian
để làm điều đó, hãy sử dụng activityViewModels()
Có thể sử dụng hàm mở rộng về lượt xem. Nếu không dùng Khung hiển thị và Kotlin, bạn có thể sử dụng các API tương tự như trên và chuyển đúng đối tượng sở hữu.
Khung hiển thị
import androidx.fragment.app.activityViewModels class MyFragment : Fragment() { // ViewModel API available in fragment.fragment-ktx // The ViewModel is scoped to the host Activity val viewModel: SharedViewModel by activityViewModels() }
Thành phần hiển thị
import androidx.lifecycle.ViewModelProvider; public class MyFragment extends Fragment { SharedViewModel viewModel; @Override public void onViewCreated(View view, Bundle savedInstanceState) { // The ViewModel is scoped to the host Activity viewModel = new ViewModelProvider(requireActivity()) .get(SharedViewModel.class); } }
Compose
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( context: Context = LocalContext.current, // ViewModel API available in lifecycle.lifecycle-viewmodel-compose // The ViewModel is scoped to the Activity of the host Fragment // where this composable function is called viewModel: SharedViewModel = viewModel( viewModelStoreOwner = (context as Fragment).requireActivity() ) ) { /* ... */ }
ViewModel thuộc phạm vi của biểu đồ Điều hướng
Biểu đồ điều hướng cũng là chủ sở hữu cửa hàng ViewModel. Nếu đang sử dụng Mảnh điều hướng hoặc thành phần Điều hướng trong Compose, bạn có thể nhận một thực thể của ViewModel trong phạm vi biểu đồ Điều hướng bằng hàm mở rộng Khung hiển thị navGraphViewModels(graphId)
.
Số lượt xem
import androidx.navigation.navGraphViewModels class MyFragment : Fragment() { // ViewModel API available in navigation.navigation-fragment // The ViewModel is scoped to the `nav_graph` Navigation graph val viewModel: SharedViewModel by navGraphViewModels(R.id.nav_graph) // Equivalent navGraphViewModels code using the viewModels API val viewModel: SharedViewModel by viewModels( { findNavController().getBackStackEntry(R.id.nav_graph) } ) }
Thành phần hiển thị
import androidx.lifecycle.ViewModelProvider; public class MyFragment extends Fragment { SharedViewModel viewModel; @Override public void onViewCreated(View view, Bundle savedInstanceState) { NavController navController = NavHostFragment.findNavController(this); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.my_graph); // The ViewModel is scoped to the `nav_graph` Navigation graph viewModel = new ViewModelProvider(backStackEntry).get(SharedViewModel.class); } }
Compose
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyAppNavHost() { // ... composable("myScreen") { backStackEntry -> // Retrieve the NavBackStackEntry of "parentNavigationRoute" val parentEntry = remember(backStackEntry) { navController.getBackStackEntry("parentNavigationRoute") } // Get the ViewModel scoped to the `parentNavigationRoute` Nav graph val parentViewModel: SharedViewModel = viewModel(parentEntry) // ... } }
Nếu đang dùng Hilt cùng với thành phần Điều hướng của Jetpack, bạn có thể sử dụng API hiltNavGraphViewModels(graphId)
như sau.
Số lượt xem
import androidx.hilt.navigation.fragment.hiltNavGraphViewModels class MyFragment : Fragment() { // ViewModel API available in hilt.hilt-navigation-fragment // The ViewModel is scoped to the `nav_graph` Navigation graph // and is provided using the Hilt-generated ViewModel factory val viewModel: SharedViewModel by hiltNavGraphViewModels(R.id.nav_graph) }
Thành phần hiển thị
import androidx.hilt.navigation.HiltViewModelFactory; import androidx.lifecycle.ViewModelProvider; public class MyFragment extends Fragment { SharedViewModel viewModel; @Override public void onViewCreated(View view, Bundle savedInstanceState) { NavController navController = NavHostFragment.findNavController(this); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.my_graph); // The ViewModel is scoped to the `nav_graph` Navigation graph // and is provided using the Hilt-generated ViewModel factory viewModel = new ViewModelProvider( backStackEntry, HiltViewModelFactory.create(getContext(), backStackEntry) ).get(SharedViewModel.class); } }
Compose
import androidx.hilt.navigation.compose.hiltViewModel @Composable fun MyAppNavHost() { // ... composable("myScreen") { backStackEntry -> val parentEntry = remember(backStackEntry) { navController.getBackStackEntry("parentNavigationRoute") } // ViewModel API available in hilt.hilt-navigation-compose // The ViewModel is scoped to the `parentNavigationRoute` Navigation graph // and is provided using the Hilt-generated ViewModel factory val parentViewModel: SharedViewModel = hiltViewModel(parentEntry) // ... } }
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- Bố cục và biểu thức liên kết
- Tổng quan về ViewModel