class: center, middle, inverse # ItbCalendar .footnote[Mateu Yábar] --- # Objectiu final .fullscreen70[![](exercicis/cityQuiz/cityQuiz.gif)] --- # ConstraintLayout - Chains - Weight https://developer.android.com/training/constraint-layout --- # ImageView - scaleType - https://thoughtbot.com/blog/android-imageview-scaletype-a-visual-guide .fullscreen70[![](img/imageview_scaletype.png)] --- # Android Theme - Configuració de l'estil de visualització del elements - manifest.xml ```xml
``` --- # Android Theme - styles.xml ```xml ``` - Theme.AppCompat - Theme.AppCompat.Light.NoActionBar --- # Material design >>> Material Design is a visual language that synthesizes the classic principles of good design with the innovation of technology and science. - https://material.io --- # Material design - Android ```gradle implementation 'com.google.android.material:material:1.0.0' ``` - Styles.xml - Theme.MaterialComponents.* - Theme.MaterialComponents.Light.NoActionBar --- # Material design - Button ```xml
``` - https://material.io/develop/android/components/material-button/ --- # Projecte City Quiz - Fes el projecte City Quiz --- # LiveData --- # Programació no reactiva - Llistat de contactes amb botó de crear
Fragment->ViewModel: getContacts() ViewModel-->>Fragment: List<Contact> Note right of ViewModel: L'usuari afegeix un contacte Fragment->ViewModel: addContact(contact) Fragment->ViewModel: getContacts() ViewModel-->>Fragment: List<Contact>
--- # Problema Threads
Fragment->ViewModel: getContacts() ViewModel->Repository: getContacts() Note right of Repository: L'operació pot tardar uns segons Repository-->>ViewModel: List<Contact> ViewModel-->>Fragment: List<Contact>
--- # Com es pinta un GUI - (1 s/60 fps = 16 ms per frame)
View->View: repaint() Note right of View: Actualització del frame View->View: repaint() View->View: repaint() View->View: repaint() View->View: repaint()
--- # GUI sense Threads - Pantalla queda 'congelada'
View->View: repaint() Note right of View: Actualització del frame View->RestApi: getContacts() Note right of RestApi: L'operació tarda més de 16ms RestApi-->>View: List<Contact> View->View: repaint() View->View: repaint()
--- # GUI amb Threads
ViewThread->ViewThread: repaint() ViewThread-->DataThread: loadContacts() Note right of DataThread: L'operació tarda però \ns'executa en un altre thread ViewThread->ViewThread: repaint() ViewThread->ViewThread: repaint() DataThread-->>ViewThread: dataAvailable() ViewThread->DataThread: getContacts() Note right of DataThread: L'operació és molt ràpida DataThread-->>ViewThread: List<Contact> ViewThread->ViewThread: repaint()
--- # GUI amb threads - Com avisem que l'operació ja acabat? - Que passa si la pantalla que havia de mostrar les dades està tancada? - ... --- # Problema editor 'desconegut'
Fragment->ViewModel: getContacts() ViewModel-->>Fragment: List< Contact> Note right of ViewModel: L'usuari afegeix un contacte Fragment2->ViewModel: addContact(contact) Note right of ViewModel: El Fragment no sap que s'ha \nafegit un contacte\n i no s'actualitza
--- # Live Data - Threads
Fragment->ViewModel: getContacts() ViewModel-->>Fragment: LiveData < List < Contact>> Fragment-->LiveData: observe() Note right of LiveData: L'operació tarda, \nperò, no bloqueja LiveData-->>Fragment: onChanged();
--- # Live Data - editor 'desconegut'
Fragment->ViewModel: getContacts() ViewModel-->>Fragment: LiveData< List< Contact>> Fragment-->LiveData: observe() LiveData-->>Fragment: onChanged(); Fragment2->ViewModel: addContact(contact) LiveData-->>Fragment: onChanged();
--- # Live Data ```gradle def lifecycle_version = "2.1.0" // ViewModel and LiveData implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" ``` --- # LiveData
```java public void observe(LifecycleOwner owner, Observer super T> observer); /* (...) */ ``` - Un fragment o una Activity són LifecycleOwners --- # Observer
``` public interface Observer
{ void onChanged(T t); } ``` --- # MutableLiveData
```java public void postValue(T value) { super.postValue(value); } ``` --- class: hide_content # LiveData - Exemple [MutableLiveDataSample.zip](examples/MutableLiveDataSample.zip)