Outils pour utilisateurs

Outils du site


lang:android:fragment

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
lang:android:fragment [2023/08/22 16:30] – Ajout des sources rootlang:android:fragment [2023/08/23 12:15] (Version actuelle) – Ajout de "Binding" root
Ligne 2: Ligne 2:
  
 [[https://developer.android.com/guide/fragments/communicate?hl=fr#java|Communiquer avec des fragments]] {{ :lang:android:fragment:communiquer_avec_des_fragments_android_developers_22_08_2023_16_08_14_.html |Archive du 30/05/2023 le 22/08/2023}} [[https://developer.android.com/guide/fragments/communicate?hl=fr#java|Communiquer avec des fragments]] {{ :lang:android:fragment:communiquer_avec_des_fragments_android_developers_22_08_2023_16_08_14_.html |Archive du 30/05/2023 le 22/08/2023}}
 +
 +Le respect des bonnes pratiques de communication devrait permettre de ne pas avoir besoin d'utiliser ''runOnUiThread(...)''.
 +====Événements====
 +
 +Seulement en Kotlin.
 +
 +[[https://developer.android.com/topic/architecture/ui-layer/events?hl=fr|Événements de l'UI]] {{ :lang:android:fragment:v_nements_de_l_ui_android_developers_23_08_2023_09_20_10_.html |Archive du 27/07/2023 le 23/08/2023}}
  
 ====FragmentResult==== ====FragmentResult====
 +
 +Communication en temps réel.
  
 On stocke dans le ''FragmentManager'' une action a effectuée quand une clé est appelée. On stocke dans le ''FragmentManager'' une action a effectuée quand une clé est appelée.
Ligne 27: Ligne 36:
  
 [[https://medium.com/e-legion/getting-the-result-right-part-2-fragment-result-api-1a17f99490dc|The right way to get a result. Part 2. Fragment Result API]] {{ :lang:android:fragment:the_right_way_to_get_a_result._part_2._fragment_result_api_by_leonid_belyakov_e-legion_medium_22_08_2023_16_29_27_.html |Archive du 31/05/2021 le 22/08/2023}} [[https://medium.com/e-legion/getting-the-result-right-part-2-fragment-result-api-1a17f99490dc|The right way to get a result. Part 2. Fragment Result API]] {{ :lang:android:fragment:the_right_way_to_get_a_result._part_2._fragment_result_api_by_leonid_belyakov_e-legion_medium_22_08_2023_16_29_27_.html |Archive du 31/05/2021 le 22/08/2023}}
 +
 +====LiveData====
 +
 +Communication en temps réel.
 +
 +LiveData est un champ qui peut être observé. Il s'implémente sur la base d'une classe ViewModel.
 +
 +<code java>
 +public class ItemViewModel extends ViewModel {
 +  private final MutableLiveData<Item> selectedItem = new MutableLiveData<Item>();
 +  public void selectItem(Item item) {
 +    selectedItem.setValue(item);
 +  }
 +  public LiveData<Item> getSelectedItem() {
 +    return selectedItem;
 +  }
 +}
 +</code>
 +
 +Ici, ''Item'' est soit une classe contenant une ou plusieurs données, soit la version classe d'un type primitif (''Boolean'', ''Float'', ...).
 +
 +Les données ''LiveData'' sont perdues à la fermeture de l'application.
 +
 +Si un observateur commence à surveiller un ''LiveData'' et qu'une valeur a déjà été assignée, la callback est immédiatement appelée (depuis le thread de l'UI).
 +
 +Un ''LiveData'' est commun à tous les éléments ayant le même cycle de vue du constructeur.
 +
 +  * Observateur
 +
 +Depuis une activity, on utilise ''this'' avec ''ViewModelProvider'' car tous les fragments vont avoir la même Activity.
 +
 +Depuis un fragment, il faut utiliser ''requireActivity()'' avec ''ViewModelProvider''.
 +
 +Pour ''observe'', il faut utiliser ''this'' avec ''onCreate'' et ''getViewLifecycleOwner()'' avec ''onViewCreated'' et ''onActivityCreated''. [[https://stackoverflow.com/questions/57081763/livedata-observing-in-fragment|LiveData observing in Fragment]] {{ :lang:android:fragment:android_-_livedata_observing_in_fragment_-_stack_overflow_23_08_2023_09_05_56_.html |Archive du 17/07/2019 le 23/08/2023}} [[https://developer.android.com/guide/components/activities/activity-lifecycle#oncreate|The activity lifecycle#oncreate]] {{ :lang:android:fragment:the_activity_lifecycle_android_developers_23_08_2023_09_08_25_.html |Archive du 24/04/2023 le 23/08/2023}} [[https://developer.android.com/reference/androidx/fragment/app/Fragment.html#getViewLifecycleOwner()|Fragment#getViewLifecycleOwner]] {{ :lang:android:fragment:fragment_android_developers_23_08_2023_09_08_50_.html |Archive du 11/08/2023 le 23/08/2023}}
 +
 +<code java>
 +public void onCreate(Bundle savedInstanceState) {
 +  super.onCreate(savedInstanceState);
 +  viewModel = new ViewModelProvider(this).get(ItemViewModel.class);
 +  viewModel.getSelectedItem().observe(this, item -> {
 +    // Perform an action with the latest item data.
 +  });
 +}
 +</code>
 +
 +  * Modificateur
 +
 +Ici, depuis un fragment, on utilise ''requireActivity'' pour les mêmes raisons que ci-dessus.
 +
 +<code java>
 +public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
 +  super.onViewCreated(view, savedInstanceState);
 +  viewModel = new ViewModelProvider(requireActivity()).get(ItemViewModel.class);
 +  ...
 +  viewModel.selectItem(item);
 +}
 +</code>
 +
 +  * Notes
 +
 +''LiveData'' (avec ses méthodes ''observe'', ''setValue'') s'utilise depuis le thread de l'UI. Sinon, il existe ''postValue'' si on est en dehors du thread de l'UI.
 +
 +Il n'est pas possible de modifier ou d'observer uniquement un champ d'un item. Si c'est nécessaire, il faut passer par 2 variables ''LiveData'' différentes.
 +
 +Si un ''LiveData'' est modifié 2 fois avant qu'un observateur soit notifié, l'observateur ne verra que la dernière valeur.
 +
 +Il n'est pas possible d'enlever une valeur à un ''LiveData''. Donc si un observateur observe un ''LiveData'' qui n'a jamais été écrit, aucun événement instantané ne sera généré. Mais si une valeur a déjà été assignée, un événement instantané sera systématiquement généré.
 +
 +<blockquote>If LiveData already has data set, it will be delivered to the observer<cite>[[https://developer.android.com/reference/androidx/lifecycle/LiveData#observe(androidx.lifecycle.LifecycleOwner,androidx.lifecycle.Observer%3C?%20super%20T%3E)|LiveData]] {{ :lang:android:fragment:livedata_android_developers_23_08_2023_11_46_53_.html |Archive du 11/08/2023 le 23/08/2023}}</cite></blockquote>
 +
 +
 +====setArguments====
 +
 +Passage de l'information avant le chargement du fragment.
 +
 +Depuis l'activity ou le fragment parent :
 +
 +<code java>
 +final Bundle bundle = new Bundle();
 +bundle.putBoolean("param", true);
 +fragment.setArguments(bundle);
 +</code>
 +
 +Depuis le fragment enfant :
 +
 +<code java>
 +requireArguments().getBoolean("param");
 +</code>
 +
 +=====Bouton back=====
 +
 +====Appel manuel====
 +
 +<code java>
 +mainActivity.getSupportFragmentManager().popBackStack();
 +</code>
 +
 +====Changement de fragment====
 +
 +Le comportement du bouton back se définit dans le ''FragmentManager'' au moment du chargement du nouveau fragment.
 +
 +<code java>
 +fragmentManager.beginTransaction()...
 +               .addToBackStack(null)
 +               .commit();
 +</code>
 +
 +Puis quand le bouton back sera appelé, les transactions seront inversées jusqu'au précédent appel à ''addToBackStack''.
 +
 +Evidemment, il est possible de faire plusieurs ''addToBackStack''. Il sera alors possible d'appuyer sur le bouton back autant de fois qu'il y aura eu de ''addToBackStack''. Chaque bouton back remontera d'un cran la pile des transactions.
 +
 +====Depuis onBackPressed event====
 +
 +Dans l'activity, il est possible de surcharger la méthode ''onBackPressed''. Mais cette méthode est dépréciée.
 +
 +Il faut utiliser :
 +
 +<code java>
 +getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
 +  @Override
 +  public void handleOnBackPressed() {
 +    // Back is pressed... Finishing the activity
 +    finish();
 +  }
 +});
 +</code>
 +
 +[[https://stackoverflow.com/questions/72634225/onbackpressed-is-deprecated-what-is-the-alternative|onBackPressed() is deprecated. What is the alternative?]] {{ :lang:android:fragment:android_-_onbackpressed_is_deprecated._what_is_the_alternative_-_stack_overflow_23_08_2023_09_36_51_.html |Archive du 27/07/2023 le 23/08/2023}}
 +
 +=====Binding=====
 +
 +Il existe ''View binding'' et ''Data binding''.
 +
 +Si l'objectif est seulement de remplacer les ''findViewById'', il faut utiliser ''View binding'' car plus léger.
 +
 +Si l'objectif est également de maîtriser les données lors de la reconstruction d'un fragment, ''Data binding'' est nécessaire.
 +
 +====View binding====
 +
 +====Data binding====
 +
 +  * Chargement du fragment
 +
 +<code java>
 +@Override
 +@Nullable
 +public View onCreateView(@NonNull final LayoutInflater inflater,
 +    @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
 +  super.onCreateView(inflater, container, savedInstanceState);
 +
 +  binding = NameFragmentBinding.inflate(inflater, container, false);
 +  binding.setLifecycleOwner(getViewLifecycleOwner());  // Uniquement nécessaire si le binding est lié à un LiveData.
 +
 +  return binding.getRoot();
 +}
 +</code>
 +
 +[[https://stackoverflow.com/questions/63336247/must-i-set-lifecycleowner-for-a-data-binding-in-android-studio)|Must I set lifecycleOwner for a data binding in Android Studio?]] {{ :lang:android:fragment:must_i_set_lifecycleowner_for_a_data_binding_in_android_studio_-_stack_overflow_23_08_2023_12_07_42_.html |Archive du 10/08/2020 le 23/08/2023}}
 +
 +[[https://developer.android.com/topic/libraries/data-binding/architecture|Bind layout views to Architecture Components]] {{ :lang:android:fragment:bind_layout_views_to_architecture_components_android_developers_23_08_2023_12_06_13_.html |Archive du 12/07/2023 le 23/08/2023}}
 +
 +  * Utilisation des LiveData
 +
 +[[https://medium.com/swlh/basic-form-validation-in-android-with-live-data-and-data-binding-cb6b1d073717|Basic Form Validation in Android with Live Data and Data Binding]] {{ :lang:android:fragment:basic_form_validation_in_android_with_live_data_and_data_binding_by_brandon_wever_the_startup_medium_23_08_2023_12_12_03_.html |Archive du 07/10/2019 le 23/08/2023}}
 +
 +====Problèmes=====
 +
 +Si une ressource ne génère pas le binding, il faut entourer la ressource par ''<layout></layout>''.
lang/android/fragment.1692714650.txt.gz · Dernière modification : 2023/08/22 16:30 de root