Slide 1

Slide 1 text

MVVM com RxJava em Kotlin no Android

Slide 2

Slide 2 text

GDGFoz Quem ? • Houssan Ali Hijazi - [email protected] • Desenvolvedor Android na www.HElabs.com • Organizador GDG Foz do Iguaçu • www.lojasnoparaguai.com.br • www.desaparecidosbr.org • www.hussan.com.br

Slide 3

Slide 3 text

GDGFoz Kotlin • 2011/JetBrains • 1.0 em Fev. 2016 • 1.1 em Mar. 2017 • Pinterest, Coursera, Netflix, Uber, Square, Trello e Basecamp • 17/Maio - Google IO 2017

Slide 4

Slide 4 text

GDGFoz Kotlin • Interoperabilidade • Null Safety • Conciso

Slide 5

Slide 5 text

GDGFoz Manifesto reativo • Responsivo - Reagir rápido • Resiliente - Reagir a falhas • Elástico - Reagir a carga / Autoescalar • Orientado a mensagens - Comunicação assíncrona Fonte: https://www.reactivemanifesto.org/pt-BR

Slide 6

Slide 6 text

GDGFoz RxJava • RxJava - Reactive Extensions para a JVM - uma biblioteca para compor programas assíncronos e baseados em eventos usando sequências observáveis. • Netflix • 1.0.0 em 18 Nov 2014 • 2.0.0 em 28 Out 2016

Slide 7

Slide 7 text

GDGFoz RxJava Observable Disposable subscribe(Observer) Emite Observer onNext(T) onComplete() onError(Throwable) Consome

Slide 8

Slide 8 text

GDGFoz RxJava • Observable - Emite dados • Observer - Consome dados • Disposable • Operators: map, flatmap, filter, last, first etc.. • Schedulers

Slide 9

Slide 9 text

GDGFoz Código • Robusto • Estável • Testável • Modular

Slide 10

Slide 10 text

GDGFoz Model/View/Controller Activity IView

Slide 11

Slide 11 text

GDGFoz Model/View/Presenter Contract

Slide 12

Slide 12 text

GDGFoz App

Slide 13

Slide 13 text

GDGFoz Model/View/Presenter // View contract interface RepositoriesContract{ interface View{ fun setRepositories(repositories: List) } } // Activity/Fragment class RepositoriesActivity : AppCompatActivity(), RepositoriesContract.View { ... // Passing the View to Presenter presenter = RepositoriesPresenter(this) override fun setRepositories(repositories: List) { // Setting data to view }

Slide 14

Slide 14 text

GDGFoz Model/View/Presenter // Presenter contract interface RepositoriesContract { interface Presenter { fun getAllRepositories() } } // Passing View to Presenter class RepositoriesPresenter(val view: RepositoriesContract.View): RepositoriesContract.Presenter lateinit var model: RepositoryModel override fun getAllRepositories() { // Call model and set data to View // Can be RxJava var repositories:List = model.getAllRepositories() view.setRepositories(repositories) }

Slide 15

Slide 15 text

GDGFoz Model/View/ViewModel • Microsoft • 2005 • Orientado à eventos

Slide 16

Slide 16 text

GDGFoz Model/View/ViewModel

Slide 17

Slide 17 text

GDGFoz MVVM // ViewModel class RepositoriesViewModel(var model: RepositoryDataSource) { ... fun getAllRepositories() { // Return an Observable fun getAllRepositories(): Observable> = model.getAllRepositories() }

Slide 18

Slide 18 text

GDGFoz MVVM // Activity/Fragment class RepositoriesActivity : AppCompatActivity() { private val viewModel: RepositoriesViewModel by lazy { RepositoriesViewModel(RepositoryModel()) } private val mDisposable = CompositeDisposable() ...

Slide 19

Slide 19 text

GDGFoz MVVM // Activity/Fragment override fun onCreate(savedInstanceState: Bundle?) { ... mDisposable.add( viewModel.getAllRepositories() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( // onNext this::setRepositories, // onError { error -> Log.d(TAG, "Error: ", error) }, // onComplete { Log.d(TAG, "Completed: ") } ) ) // Activity/Fragment fun setRepositories(repositories: List) { // Setting data to view }

Slide 20

Slide 20 text

GDGFoz Android lifecycle // Activity/Fragment override fun onDestroy() { super.onDestroy() mDisposable.dispose() }

Slide 21

Slide 21 text

GDGFoz MVP/MVVM class Presenter: IPresenter { override fun getAllRepositories() { ... view.setRepositories(repositories) } } class ViewModel { fun getAllRepositories(): Observable> { ... } }

Slide 22

Slide 22 text

GDGFoz MVVM tests class RepositoriesViewModelTest { @Mock lateinit var model: RepositoryDataSource lateinit var viewModel: RepositoriesViewModel … @Before fun setup() { model = mock() viewModel = RepositoriesViewModel(model) }

Slide 23

Slide 23 text

GDGFoz MVVM tests @Test fun `get repositories emit correct values`() { val repositories = listOf(Repository(name = "Test"), Repository(name = "Test2" `when`(model.getAllRepositories()).thenReturn(Observable.just(repositories)) viewModel.getAllRepositories() .test() .assertNoErrors() .assertComplete() .assertValue(repositories) }

Slide 24

Slide 24 text

GDGFoz Save states // Save override fun onSaveInstanceState(state: Bundle?) { super.onSaveInstanceState(state) //Can create Bundle here state.putAll(viewModel.getState()) } // Restore override fun onRestoreInstanceState(bundle: Bundle) { super.onRestoreInstanceState(bundle) viewModel.restoreState(bundle) }

Slide 25

Slide 25 text

GDGFoz Activity Fragment CustomView CustomView P / VM View

Slide 26

Slide 26 text

GDGFoz Lógica de UI ? • Tem lógica de UI ? • Sim - Presenter/ViewModel (Testes) • Não - View

Slide 27

Slide 27 text

GDGFoz Qual ? • Classes Android sem lógica ? • Pode ser testado (unit test) ? • Suas classes tem uma responsabilidade bem definida ?

Slide 28

Slide 28 text

GDGFoz Links • http://reactivex.io/ • https://github.com/ReactiveX/RxJava/ • https://kotlinlang.org/ • https://medium.com/upday-devs/android-architecture-patterns-part-3- model-view-viewmodel-e7eeee76b73b • https://github.com/googlesamples/android-architecture • https://github.com/hussanhijazi/retrofit-rxjava-databinding/tree/kotlin-mvvm

Slide 29

Slide 29 text

Obrigado