API การกำหนดขอบเขตของ ViewModel (Views)   ซึ่งเป็นส่วนหนึ่งของ Android Jetpack.

แนวคิดและการใช้งาน Jetpack Compose

ขอบเขตเป็นสิ่งสำคัญในการใช้ ViewModel อย่างมีประสิทธิภาพ ViewModel แต่ละรายการจะมีขอบเขตเป็นออบเจ็กต์ที่ใช้ ViewModelStoreOwner อินเทอร์เฟซ โดยมี API หลายรายการที่ช่วยให้คุณจัดการขอบเขตของ ViewModel ได้ง่ายขึ้น

เมธอด ViewModelProvider.get() ช่วยให้คุณได้รับอินสแตนซ์ของ ViewModel ที่กำหนดขอบเขตเป็น ViewModelStoreOwner ใดก็ได้ สำหรับผู้ใช้ Kotlin จะมีฟังก์ชันส่วนขยายต่างๆ ให้ใช้งานในกรณีการใช้งานที่พบบ่อยที่สุด การใช้งานฟังก์ชันส่วนขยาย Kotlin ทั้งหมดใช้ ViewModelProvider API เบื้องหลัง

ViewModel ที่กำหนดขอบเขตเป็น ViewModelStoreOwner ที่ใกล้ที่สุด

คุณสามารถกำหนดขอบเขตของ ViewModel เป็นกิจกรรม, Fragment หรือปลายทางของกราฟการนำทางได้ ฟังก์ชันส่วนขยาย viewModels()ที่จัดทำโดยไลบรารี Activity, Fragment และ Navigation ช่วยให้คุณได้รับอินสแตนซ์ของ ViewModel ที่กำหนดขอบเขตเป็น ViewModelStoreOwner ที่ใกล้ที่สุด

Views

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

Views

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 ที่กำหนดขอบเขตเป็น ViewModelStoreOwner ใดก็ได้

ฟังก์ชัน ComponentActivity.viewModels() และ Fragment.viewModels() ในระบบ View จะใช้พารามิเตอร์ ownerProducer ที่ไม่บังคับ ซึ่งคุณสามารถใช้เพื่อระบุ ViewModelStoreOwner ที่อินสแตนซ์ของ ViewModel กำหนดขอบเขตไว้ ตัวอย่างต่อไปนี้แสดงวิธีรับอินสแตนซ์ของ ViewModel ที่กำหนดขอบเขตเป็น Fragment หลัก

Views

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

Views

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 ที่กำหนดขอบเขตเป็นกิจกรรมจาก Fragment เป็นกรณีการใช้งานที่พบบ่อย เมื่อดำเนินการดังกล่าว คุณสามารถใช้ฟังก์ชันส่วนขยาย activityViewModels() Views ได้ หากคุณไม่ได้ใช้ Views และ Kotlin คุณสามารถใช้ API เดียวกับด้านบนได้โดยส่งเจ้าของที่เหมาะสม

Views

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

Views

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 ที่กำหนดขอบเขตเป็นกราฟการนำทาง

กราฟการนำทางยังเป็นเจ้าของที่เก็บ ViewModel ด้วย หากคุณใช้ Navigation Fragment คุณจะได้รับอินสแตนซ์ของ ViewModel ที่กำหนดขอบเขตเป็นกราฟการนำทางด้วยฟังก์ชันส่วนขยาย navGraphViewModels(graphId) Views

Views

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

Views

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

หากคุณใช้ Hilt นอกเหนือจาก Jetpack Navigation คุณสามารถใช้ hiltNavGraphViewModels(graphId) API ได้ดังนี้

Views

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

Views

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