ViewModel 範圍設定 API (檢視區塊)   Android Jetpack 的一部分。

概念和 Jetpack Compose 實作

範圍是有效使用 ViewModel 的關鍵。每個 ViewModel 的範圍都是限定為實作 ViewModelStoreOwner 介面的物件。您可以運用幾種 API 更輕鬆管理 ViewModel 的範圍。

ViewModelProvider.get() 方法可讓您取得範圍限定為任何 ViewModelStoreOwner 的 ViewModel 執行個體。如果是 Kotlin 使用者,針對常見的用途提供不同的擴充功能。所有 Kotlin 擴充功能函式實作都會使用 ViewModelProvider API 進階功能。

將 ViewModel 範圍限定為最接近的 ViewModelStoreOwner

您可以將 ViewModel 的範圍限定為活動、片段或導覽圖的目的地。依活動、片段和 Navigation 程式庫提供的 viewModels() 擴充功能函式,可讓您取得 ViewModel 範圍限定為最接近 ViewModelStoreOwner 的執行個體。

觀看次數

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

觀看次數

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

範圍限定為任何 ViewModelStoreOwner 的 ViewModel

檢視畫面系統中的 ComponentActivity.viewModels()Fragment.viewModels() 函式使用選用 ownerProducer 參數,可用於指定 ViewModel 的範圍限定哪個 ViewModelStoreOwner 執行個體。以下範例說明如何取得 ViewModel 範圍限定為父項片段的執行個體:

觀看次數

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

觀看次數

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

從片段中取得範圍限定為活動的 ViewModel 是一種常見的用途。方法是使用 activityViewModels() 檢視畫面擴充功能函式。如果您使用的不是 View 和 Kotlin,則可以使用相同的 API 並傳遞正確的擁有者。

觀看次數

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

觀看次數

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

範圍限定為 Navigation 圖形的 ViewModel

Navigation 圖表也是 ViewModel 儲存區擁有者。使用 Navigation Fragment 時,您可以透過 navGraphViewModels(graphId) 檢視畫面擴充功能函式,取得 ViewModel 範圍限定為 Navigation 圖表的執行個體。

觀看次數

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

觀看次數

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

除了 Jetpack Navigation 之外,如果您還使用 Hilt,則可以如下所示使用 hiltNavGraphViewModels(graphId) API。

觀看次數

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

觀看次數

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