Uygulamanız için gezinmeyi tasarlarken en az koşullu mantığa göre bir diğerini seçin. Örneğin, Kullanıcının giriş yapmasını gerektiren bir hedefe giden derin bağlantıyı izleyebilir ya da oyuncunun ne zaman oynayacağı oyunda farklı veya kayba uğrayabilir.
Kullanıcı girişi
Bu örnekte, bir kullanıcı kimlik doğrulama. Bu işlem kimlik doğrulama gerektirdiğinden, kullanıcı kimliği doğrulanmamışsa bir giriş ekranına yönlendirilir.
Bu örnek için gezinme grafiği şöyle görünebilir:
Kimlik doğrulaması için uygulamanın login_fragment
konumuna gitmesi gerekir. Burada kullanıcı
kimlik doğrulaması için bir kullanıcı adı ve şifre girebilir. Kabul edilirse kullanıcı
profile_fragment
ekranına geri gönderildi. Kabul edilmezse kullanıcı
kimlik bilgilerinin geçersiz olduğunu bildirmek için bir
Snackbar
.
Kullanıcı giriş yapmadan profil ekranına geri dönerse
main_fragment
ekranına gönderildi.
Aşağıda bu uygulamaya ilişkin gezinme grafiği verilmiştir:
<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
, kullanıcının profilini görüntülemek için tıklayabileceği bir düğme içeriyor.
Profil ekranını görmek isteyen kullanıcılar öncelikle kimliğini doğrulamalıdır. Bu
etkileşim iki ayrı parça kullanılarak modellenir, ancak
kullanıcı durumu. Bu eyalet bilgilerinin sorumluluğu, aşağıdakilerden herhangi birinin sorumluluğunda değildir
daha uygun bir şekilde ortak bir UserViewModel
içinde tutulmasını sağlar.
Bu ViewModel
, etkinlikle ilgili kapsamı belirlenerek parçalar arasında paylaşılır.
ViewModelStoreOwner
uygular. Aşağıdaki örnekte,
requireActivity()
ana makine MainActivity
olduğundan MainActivity
olarak çözümlenir
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
uygulamasındaki kullanıcı verileri LiveData
üzerinden açığa çıkar. Bu verilere, nerede erişileceğine karar verilir.
bu verileri gözlemlemeniz gerekir. Gittikten sonra
ProfileFragment
, kullanıcı verileri aşağıdaki gibiyse uygulama bir karşılama mesajı gösterir:
devam eder. Kullanıcı verileri null
ise LoginFragment
bölümüne gidersiniz.
çünkü kullanıcının profilini görebilmek için kimlik doğrulaması yapması gerekir. Tanımlayın
aşağıdaki örnekte gösterildiği gibi ProfileFragment
etiketinizde karar verme mantığı:
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
hedefine ulaştıklarında kullanıcı verileri null
ise
LoginFragment
alanına yönlendirildi.
Tekliflerinizi otomatikleştirmek ve optimize etmek için
NavController.getPreviousBackStackEntry()
almak için NavBackStackEntry
önceki hedefe ilişkin NavController
'a özgü
durumudur. LoginFragment
,
SavedStateHandle
önceki NavBackStackEntry
ile
kullanıcı başarıyla giriş yaptı. Bu, eğer şu durumda geri dönmek isteyeceğimiz eyalettir:
kullanıcının hemen sistem geri düğmesine basması gerekir. Bu durumu ayarlama
SavedStateHandle
kullanılması, durumun süreç ölümü boyunca devam etmesini sağlar.
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); } }
Kullanıcı bir kullanıcı adı ve şifre girdikten sonra,
Kimlik doğrulama için UserViewModel
. Kimlik doğrulama başarılı olursa
UserViewModel
, kullanıcı verilerini depolar. Ardından LoginFragment
,
SavedStateHandle
üzerinde LOGIN_SUCCESSFUL
değeri var ve otomatik olarak ekrandan çıkıyor
hazırlar.
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 } }
Kimlik doğrulamayla ilgili tüm mantığın
UserViewModel
Bu, kurumun sorumluluğunda olmadığı için önemlidir.
belirlemek için LoginFragment
veya ProfileFragment
kimlik doğrulaması yapılmış. Mantığınızı bir ViewModel
içine almak,
test edilmesi de daha kolay olur. Gezinme mantığınız karmaşıksa
bu mantığı özellikle test ederek doğrulamanız gerekir. Bkz.
Daha fazla bilgi için uygulama mimarisi rehberi
uygulamanızın mimarisini test edilebilir bileşenlere göre yapılandırma.
ProfileFragment
içinde, LOGIN_SUCCESSFUL
değeri
SavedStateHandle
,
onCreate()
yöntemidir. Kullanıcı ProfileFragment
geri döndüğünde LOGIN_SUCCESSFUL
kontrol edilir. Değer false
ise kullanıcı geri yönlendirilebilir
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); } }); } ... }
Kullanıcı başarıyla giriş yaparsa ProfileFragment
, ekranda bir
karşılama mesajı.
Burada sonucu kontrol etmek için kullanılan teknik, birbirinizle :
- Kullanıcının giriş yapmadığı ve hesabının istenmesi gereken ilk durum giriş yapın.
- Kullanıcı, giriş yapmamayı seçtiği için giriş yapmamıştır. (
false
).
Bu kullanım alanlarını birbirinden ayırt ederek size sürekli olarak kullanıcının giriş yapmasını sağlar. Başarısız destek kayıtlarının ele alınması için iş mantığı size bağlıdır ve kullanıcının uygulamayı neden tekrar etmesi gerektiğini açıklayan bir yer paylaşımı görüntüleyebilir. Giriş yapma, tüm etkinliği tamamlama veya kullanıcıyı bir hedefe yönlendirme (ör. önceki kod örneğinde olduğu gibi) giriş gerektirmeyen yeni bir kod oluşturun.