API ViewModel Scoping (Khung hiển thị)   Một phần của Android Jetpack.

Khái niệm và cách triển khai Jetpack Compose

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.

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 do thư viện Hoạt động, Mảnh và Điều hướng cung cấp, 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.viewModels()

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()
}

Khung 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);
}

ViewModel thuộc phạm vi của ViewModelStoreOwner bất kỳ

Hàm ComponentActivity.viewModels()Fragment.viewModels() trong hệ thống Khung hiển thị 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() }
    )
}

Khung 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);
    }
}

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. Khi làm như vậy, bạn có thể sử dụng hàm mở rộng Khung hiển thị activityViewModels(). 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()
}

Khung 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);
    }
}

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, 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 navGraphViewModels(graphId) Khung hiển thị.

Khung hiển thị

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) }
    )
}

Khung 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);
    }
}

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)
}

Khung 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);
    }
}