अपने ऐप्लिकेशन के लिए नेविगेशन डिज़ाइन करते समय, आपके पास इनमें से किसी एक गंतव्य बनाम अन्य. उदाहरण के लिए, अगर किसी उपयोगकर्ता ने किसी ऐसे डेस्टिनेशन के डीप लिंक पर जा सकता है जिसके लिए उपयोगकर्ता को लॉग करना ज़रूरी है या गेम में अलग-अलग डेस्टिनेशन हो सकते हैं. जीत या हार मिली.
उपयोगकर्ता लॉगिन
इस उदाहरण में, कोई उपयोगकर्ता ऐसी प्रोफ़ाइल स्क्रीन पर जाने की कोशिश करता है जिसके लिए पुष्टि करने के लिए. इस कार्रवाई के लिए पुष्टि ज़रूरी है, इसलिए उपयोगकर्ता को यह करना चाहिए अगर उपयोगकर्ता की पुष्टि पहले से नहीं की गई है, तो उन्हें लॉगिन स्क्रीन पर रीडायरेक्ट कर दिया जाएगा.
इस उदाहरण के लिए नेविगेशन ग्राफ़ कुछ ऐसा दिख सकता है:
पुष्टि करने के लिए, ऐप्लिकेशन को login_fragment
पर जाना होगा, जहां उपयोगकर्ता
प्रमाणित करने के लिए उपयोगकर्ता नाम और पासवर्ड डाल सकते हैं. इसे स्वीकार किए जाने पर, उपयोगकर्ता
profile_fragment
पर वापस भेजी गई. अगर इसे स्वीकार नहीं किया जाता है, तो उपयोगकर्ता
यह सूचना दी गई है कि उनके क्रेडेंशियल अमान्य हैं. इसके लिए,
Snackbar
.
अगर उपयोगकर्ता लॉग इन किए बिना प्रोफ़ाइल स्क्रीन पर वापस जाता है, तो उसे
main_fragment
की स्क्रीन पर भेजा गया.
यहां इस ऐप्लिकेशन का नेविगेशन ग्राफ़ दिया गया है:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/main_fragment">
<fragment
android:id="@+id/main_fragment"
android:name="com.google.android.conditionalnav.MainFragment"
android:label="fragment_main"
tools:layout="@layout/fragment_main">
<action
android:id="@+id/navigate_to_profile_fragment"
app:destination="@id/profile_fragment"/>
</fragment>
<fragment
android:id="@+id/login_fragment"
android:name="com.google.android.conditionalnav.LoginFragment"
android:label="login_fragment"
tools:layout="@layout/login_fragment"/>
<fragment
android:id="@+id/profile_fragment"
android:name="com.google.android.conditionalnav.ProfileFragment"
android:label="fragment_profile"
tools:layout="@layout/fragment_profile"/>
</navigation>
MainFragment
में एक बटन होता है, जिस पर क्लिक करके उपयोगकर्ता अपनी प्रोफ़ाइल देख सकते हैं.
अगर उपयोगकर्ता प्रोफ़ाइल स्क्रीन देखना चाहता है, तो पहले उसे अपनी पहचान की पुष्टि करनी होगी. यह
इंटरैक्शन को दो अलग-अलग फ़्रैगमेंट का इस्तेमाल करके मॉडल किया जाता है. हालांकि, यह शेयर किए गए
उपयोगकर्ता की स्थिति. राज्य की यह जानकारी इनमें से किसी के लिए भी ज़िम्मेदार नहीं है
ये दो फ़्रैगमेंट शेयर किए गए हैं. साथ ही, इन्हें शेयर किए गए UserViewModel
में बेहतर तरीके से रखा गया है.
इस ViewModel
को गतिविधि से जोड़कर, फ़्रैगमेंट के बीच शेयर किया गया है,
जो ViewModelStoreOwner
को लागू करता है. नीचे दिए गए उदाहरण में,
requireActivity()
, MainActivity
में बदल जाता है, क्योंकि MainActivity
होस्ट
ProfileFragment
:
Kotlin
class ProfileFragment : Fragment() { private val userViewModel: UserViewModel by activityViewModels() ... }
Java
public class ProfileFragment extends Fragment { private UserViewModel userViewModel; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); userViewModel = new ViewModelProvider(requireActivity()).get(UserViewModel.class); ... } ... }
UserViewModel
में उपयोगकर्ता का डेटा, LiveData
से बिना अनुमति के सार्वजनिक किया जाता है. इससे यह तय किया जा सकता है कि
आपको इस डेटा पर नज़र रखनी होगी. नेविगेट करने पर
ProfileFragment
, अगर उपयोगकर्ता का डेटा
उपस्थित. अगर उपयोगकर्ता का डेटा null
है, तो LoginFragment
पर जाएं,
क्योंकि उपयोगकर्ता को अपनी प्रोफ़ाइल देखने से पहले खाते की पुष्टि करनी होगी. परिभाषित करें
आपके ProfileFragment
में लॉजिक, जैसा कि इस उदाहरण में दिखाया गया है:
Kotlin
class ProfileFragment : Fragment() { private val userViewModel: UserViewModel by activityViewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val navController = findNavController() userViewModel.user.observe(viewLifecycleOwner, Observer { user -> if (user != null) { showWelcomeMessage() } else { navController.navigate(R.id.login_fragment) } }) } private fun showWelcomeMessage() { ... } }
Java
public class ProfileFragment extends Fragment { private UserViewModel userViewModel; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); userViewModel = new ViewModelProvider(requireActivity()).get(UserViewModel.class); final NavController navController = Navigation.findNavController(view); userViewModel.user.observe(getViewLifecycleOwner(), (Observer<User>) user -> { if (user != null) { showWelcomeMessage(); } else { navController.navigate(R.id.login_fragment); } }); } private void showWelcomeMessage() { ... } }
अगर उपयोगकर्ता का डेटा ProfileFragment
तक पहुंचने के बाद null
है, तो इसका मतलब है कि
LoginFragment
पर रीडायरेक्ट किया गया.
Google Analytics 4 पर माइग्रेट करने के लिए,
NavController.getPreviousBackStackEntry()
NavBackStackEntry
को फिर से पाने के लिए
पिछले गंतव्य के लिए, जो NavController
-विशिष्ट
गंतव्य की जानकारी दें. LoginFragment
कुल SavedStateHandle
पिछले NavBackStackEntry
का इस्तेमाल करके शुरुआती वैल्यू सेट करें. इससे यह पता चलेगा कि
उपयोगकर्ता ने सफलतापूर्वक लॉग इन कर लिया है. यह वह राज्य है जिसे हम तब वापस लौटाना चाहेंगे, जब
उपयोगकर्ता को तुरंत सिस्टम के 'वापस जाएं' बटन को दबाना पड़ता था. इस स्थिति को सेट किया जा रहा है
SavedStateHandle
का इस्तेमाल करने से यह पक्का होता है कि प्रोसेस के बंद होने के बाद भी स्थिति बनी रहेगी.
Kotlin
class LoginFragment : Fragment() { companion object { const val LOGIN_SUCCESSFUL: String = "LOGIN_SUCCESSFUL" } private val userViewModel: UserViewModel by activityViewModels() private lateinit var savedStateHandle: SavedStateHandle override fun onViewCreated(view: View, savedInstanceState: Bundle?) { savedStateHandle = findNavController().previousBackStackEntry!!.savedStateHandle savedStateHandle.set(LOGIN_SUCCESSFUL, false) } }
Java
public class LoginFragment extends Fragment { public static String LOGIN_SUCCESSFUL = "LOGIN_SUCCESSFUL" private UserViewModel userViewModel; private SavedStateHandle savedStateHandle; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { userViewModel = new ViewModelProvider(requireActivity()).get(UserViewModel.class); savedStateHandle = Navigation.findNavController(view) .getPreviousBackStackEntry() .getSavedStateHandle(); savedStateHandle.set(LOGIN_SUCCESSFUL, false); } }
उपयोगकर्ता नाम और पासवर्ड डालने के बाद, उसे
पुष्टि करने के लिए UserViewModel
. अगर पुष्टि सफल होती है, तो
UserViewModel
में उपयोगकर्ता का डेटा सेव होता है. इसके बाद, LoginFragment
SavedStateHandle
पर LOGIN_SUCCESSFUL
मान और अपने आप बंद हो जाता है
पिछली गतिविधियां.
Kotlin
class LoginFragment : Fragment() { companion object { const val LOGIN_SUCCESSFUL: String = "LOGIN_SUCCESSFUL" } private val userViewModel: UserViewModel by activityViewModels() private lateinit var savedStateHandle: SavedStateHandle override fun onViewCreated(view: View, savedInstanceState: Bundle?) { savedStateHandle = findNavController().previousBackStackEntry!!.savedStateHandle savedStateHandle.set(LOGIN_SUCCESSFUL, false) val usernameEditText = view.findViewById(R.id.username_edit_text) val passwordEditText = view.findViewById(R.id.password_edit_text) val loginButton = view.findViewById(R.id.login_button) loginButton.setOnClickListener { val username = usernameEditText.text.toString() val password = passwordEditText.text.toString() login(username, password) } } fun login(username: String, password: String) { userViewModel.login(username, password).observe(viewLifecycleOwner, Observer { result -> if (result.success) { savedStateHandle.set(LOGIN_SUCCESSFUL, true) findNavController().popBackStack() } else { showErrorMessage() } }) } fun showErrorMessage() { // Display a snackbar error message } }
Java
public class LoginFragment extends Fragment { public static String LOGIN_SUCCESSFUL = "LOGIN_SUCCESSFUL" private UserViewModel userViewModel; private SavedStateHandle savedStateHandle; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { userViewModel = new ViewModelProvider(requireActivity()).get(UserViewModel.class); savedStateHandle = Navigation.findNavController(view) .getPreviousBackStackEntry() .getSavedStateHandle(); savedStateHandle.set(LOGIN_SUCCESSFUL, false); EditText usernameEditText = view.findViewById(R.id.username_edit_text); EditText passwordEditText = view.findViewById(R.id.password_edit_text); Button loginButton = view.findViewById(R.id.login_button); loginButton.setOnClickListener(v -> { String username = usernameEditText.getText().toString(); String password = passwordEditText.getText().toString(); login(username, password); }); } private void login(String username, String password) { userViewModel.login(username, password).observe(viewLifecycleOwner, (Observer<LoginResult>) result -> { if (result.success) { savedStateHandle.set(LOGIN_SUCCESSFUL, true); NavHostFragment.findNavController(this).popBackStack(); } else { showErrorMessage(); } }); } private void showErrorMessage() { // Display a snackbar error message } }
ध्यान दें कि पुष्टि करने से जुड़े सभी लॉजिक,
UserViewModel
. यह महत्वपूर्ण है, क्योंकि यह आपकी ज़िम्मेदारी नहीं है
LoginFragment
या ProfileFragment
से यह पता लगाया जा सकता है कि उपयोगकर्ता कैसे हैं
पुष्टि की गई है. अपने लॉजिक को ViewModel
में एन्क्रिप्ट करने से, न सिर्फ़
शेयर करने में आसान लेकिन परीक्षण करने में भी आसान. अगर आपका नेविगेशन लॉजिक जटिल है,
आपको खास तौर पर इस लॉजिक की पुष्टि टेस्ट के ज़रिए करनी चाहिए. ज़्यादा जानकारी के लिए,
इनके बारे में ज़्यादा जानकारी के लिए, ऐप्लिकेशन के आर्किटेक्चर की गाइड
टेस्ट किए जा सकने वाले कॉम्पोनेंट के आस-पास अपने ऐप्लिकेशन के आर्किटेक्चर को तैयार करना.
ProfileFragment
में वापस, LOGIN_SUCCESSFUL
मान
SavedStateHandle
को इसमें देखा जा सकता है:
onCreate()
तरीका. जब उपयोगकर्ता ProfileFragment
पर वापस आता है, तो LOGIN_SUCCESSFUL
मान की जांच की जाएगी. अगर वैल्यू false
है, तो उपयोगकर्ता को वापस रीडायरेक्ट किया जा सकता है
MainFragment
तक.
Kotlin
class ProfileFragment : Fragment() { ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val navController = findNavController() val currentBackStackEntry = navController.currentBackStackEntry!! val savedStateHandle = currentBackStackEntry.savedStateHandle savedStateHandle.getLiveData<Boolean>(LoginFragment.LOGIN_SUCCESSFUL) .observe(currentBackStackEntry, Observer { success -> if (!success) { val startDestination = navController.graph.startDestination val navOptions = NavOptions.Builder() .setPopUpTo(startDestination, true) .build() navController.navigate(startDestination, null, navOptions) } }) } ... }
Java
public class ProfileFragment extends Fragment { ... @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); NavController navController = NavHostFragment.findNavController(this); NavBackStackEntry navBackStackEntry = navController.getCurrentBackStackEntry(); SavedStateHandle savedStateHandle = navBackStackEntry.getSavedStateHandle(); savedStateHandle.getLiveData(LoginFragment.LOGIN_SUCCESSFUL) .observe(navBackStackEntry, (Observer<Boolean>) success -> { if (!success) { int startDestination = navController.getGraph().getStartDestination(); NavOptions navOptions = new NavOptions.Builder() .setPopUpTo(startDestination, true) .build(); navController.navigate(startDestination, null, navOptions); } }); } ... }
अगर उपयोगकर्ता ने सही तरीके से लॉग इन कर लिया है, तो ProfileFragment
वेलकम मैसेज.
नतीजे की जांच करने के लिए, यहां इस्तेमाल की गई तकनीक का इस्तेमाल करके, अंतर करने के लिए यह तरीका अपनाया जा सकता है दो भिन्न मामलों के बीच में:
- शुरुआती स्थिति, जहां उपयोगकर्ता ने लॉग इन नहीं किया है और उसे ऐसा करने के लिए कहा जाना चाहिए लॉगिन करें.
- उपयोगकर्ता ने लॉग इन नहीं किया है, क्योंकि उन्होंने लॉग इन न करने का विकल्प चुना (इसकी वजह से
false
).
इस्तेमाल के इन उदाहरणों में अंतर करके, उपयोगकर्ताओं से बार-बार उपयोगकर्ता लॉगिन करें. गड़बड़ी के मामलों को मैनेज करने के लिए, कारोबारी नियम आपके हिसाब से तय किए जाते हैं और इसमें ऐसा ओवरले दिखाया जा सकता है जो बताता हो कि उपयोगकर्ता को लॉगिन करना, पूरी गतिविधि को पूरा करना या उपयोगकर्ता को किसी डेस्टिनेशन पर रीडायरेक्ट करना के लिए लॉगिन की आवश्यकता नहीं होती, जैसा कि पिछले कोड उदाहरण में किया गया था.