SlideShare une entreprise Scribd logo
1  sur  105
Télécharger pour lire hors ligne
@fabioCollini
Fabio Collini
Architectures in the
Compose World
Architecture
State
UI
state event
https://developer.android.com/jetpack/compose/architecture
https://developer.android.com/jetpack/compose/architecture
State
UI
state event
State
UI
state event
State
Composable
state event
ViewModel
Composable
state event
ViewModel
Composable
UseCase
state event
ViewModel
Composable
UseCase
Repository
state event
ViewModel
Composable
UseCase
Repository
state event
source of truth
ViewModel
Composable
UseCase
Repository
state event
state event
source of truth
ViewModel
Composable
UseCase
Repository
state event
state event
state event
source of truth
MVVM / MVI
MVVM
/
MVI
Both MVVM and MVI are
unidirectional data
fl
ow
architectures
MVVM
The ViewModel accepts
events and exposes the
state
MVI
The state is a single
immutable object
MVI
The state is a single
immutable object


The events are managed
using a
fl
ow
UI = f(state)
UI = f(state)
always
UI = f(state)
always


most of the times
https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150
https://proandroiddev.com/android-singleliveevent-redux-with-kotlin-
fl
ow-b755c70bb055
SingleLiveEvent


SharedFlow


Channel


State + LaunchedEffect
SingleLiveEvent


SharedFlow


Channel


State + LaunchedEffect


Lots of edge cases :(


Not an of
fi
cial solution yet
State
MVI
The state is a single
immutable object
data class State(

val notes: List<Note>,

/
/
.
.
.


)
data class State(

val notes: List<Note>,

/
/
.
.
.


)

data class Note(

val id: Int,

val title: String,

val checked: Boolean

)
@Composable

fun Notes(state: State, onCheckedChange: (Note)
-
>
Unit) {

/
/
.
.
.


}
Notes(

state = state,

onCheckedChange = { noteToToggle
-
>


state = state.copy(

notes = state.notes

.map { note
-
>


if (note.id
=
=
noteToToggle.id) {

note.copy(checked = !note.checked)

} else {

note

}

}

)

}

)
Notes(

state = state,

onCheckedChange = { noteToToggle
-
>


state = state.copy(

notes = state.notes

.map { note
-
>


if (note.id
=
=
noteToToggle.id) {

note.copy(checked = !note.checked)

} else {

note

}

}

)

}

)
data class Note(

val id: Int,

val title: String,

val checked: Boolean

)
data class Note(

val id: Int,

val title: String,

var checked: Boolean

)_
data class Note(

val id: Int,

val title: String,

var checked: Boolean

)_

Notes(

state = state,

onCheckedChange = { noteToToggle
-
>


state = state.copy(

notes = state.notes

.map { note
-
>


if (note.id
=
=
noteToToggle.id) {

note.copy(checked = !note.checked)

} else {

note

}

}

)

}

)
data class Note(

val id: Int,

val title: String,

var checked: Boolean

)

Notes(

state = state,

onCheckedChange = { noteToToggle
-
>


noteToToggle.checked = !noteToToggle.checked

}

)
Not
so
easy…
https://developer.android.com/reference/kotlin/androidx/compose/runtime/Immutable
https://developer.android.com/reference/kotlin/androidx/compose/runtime/Stable
data class Note(

val id: Int,

val title: String,

var checked: Boolean

)

Notes(

state = state,

onCheckedChange = { noteToToggle
-
>


noteToToggle.checked = !noteToToggle.checked

}

)
data class Note(

val id: Int,

val title: String,

) {

var checked: Boolean by mutableStateOf(false)

}

Notes(

state = state,

onCheckedChange = { noteToToggle
-
>


noteToToggle.checked = !noteToToggle.checked

}

)
Composable
Xml
fi
les Composables
Xml
fi
les


Custom Views
Composables
Xml
fi
les


Custom Views


Fragments
Composables
Xml
fi
les


Custom Views


Fragments


Activities
Composables
Xml
fi
les Composables
Xml
fi
les
Composables


with


state hoisting
Custom Views Composables
Custom Views
Composables


with


remember /


rememberSavable
Fragments


Activities
Composables
Fragments


Activities
Screens


with


ViewModel
Fragments


Activities
Screens


with


ViewModel
Composables


with


remember /


rememberSavable
Custom Views
Composables


with


state hoisting
Xml
fi
les
Screen
class MyFragment : Fragment() {

override fun onCreateView(
.
.
.
) = 

ComposeView(requireContext()).apply {

setContent {

MyScreen()

}

}

}
class MyFragment : Fragment() {

override fun onCreateView(
.
.
.
) = 

ComposeView(requireContext()).apply {

setContent {

MyScreen()

}
_
_


}_

}

@Composable

fun MyScreen() {

/
/
.
.
.


}
class MyFragment : Fragment() {

override fun onCreateView(
.
.
.
) = 

ComposeView(requireContext()).apply {

viewLifecycleOwner.lifecycleScope.launch {

/
/
.
.
.


}

setContent {

MyScreen()

}
_
_


}_

}

@Composable

fun MyScreen() {

/
/
.
.
.


}
class MyFragment : Fragment() {

override fun onCreateView(
.
.
.
) = 

ComposeView(requireContext()).apply {

viewLifecycleOwner.lifecycleScope.launch {

/
/
.
.
.


}

setContent {

MyScreen()

}

}

}

@Composable

fun MyScreen() {

/
/
.
.
.


val scope = rememberCoroutineScope()

}
class MyFragment : Fragment() {

override fun onCreateView(
.
.
.
) = 

ComposeView(requireContext()).apply {

viewLifecycleOwner.lifecycleScope.launch {

/
/
.
.
.


}

setContent {

MyScreen()

}

}

}

@Composable

fun MyScreen() {

/
/
.
.
.


val scope = rememberCoroutineScope()

LaunchedEffect("
.
.
.
") {

/
/
.
.
.


}

}
https://developer.android.com/jetpack/compose/lifecycle
https://developer.android.com/jetpack/compose/lifecycle
@Singleton

class MyClass @Inject constructor() {

/
/
.
.
.


}
@Singleton

class MyClass @Inject constructor() {

/
/
.
.
.


}

@AndroidEntryPoint

class MyFragment : Fragment() {

@Inject

lateinit var myInstance: MyClass

/
/
.
.
.


}
@Singleton

class MyClass @Inject constructor() {

/
/
.
.
.


}
@Singleton

class MyClass @Inject constructor() {

/
/
.
.
.


}

@InstallIn(SingletonComponent
:
:
class)

@EntryPoint

interface MyEntryPoint {

val myInstance: MyClass

}
@Composable

inline fun <reified T : Any> rememberSingletonEntryPoint(): T {

val context = LocalContext.current

return remember {

EntryPointAccessors.fromApplication(context, T
:
:
class.java)

}

}
@Singleton

class MyClass @Inject constructor() {

/
/
.
.
.


}

@InstallIn(SingletonComponent
:
:
class)

@EntryPoint

interface MyEntryPoint {

val myInstance: MyClass

}
@Singleton

class MyClass @Inject constructor() {

/
/
.
.
.


}

@InstallIn(SingletonComponent
:
:
class)

@EntryPoint

interface MyEntryPoint {

val myInstance: MyClass

}

@Composable

fun MyScreen() {

val entryPoint = rememberSingletonEntryPoint<MyEntryPoint>()

val myInstance = entryPoint.myInstance

}
@ActivityScoped

class MyClass @Inject constructor() {

/
/
.
.
.


}

@InstallIn(ActivityComponent
:
:
class)

@EntryPoint

interface MyEntryPoint {

val myInstance: MyClass

}

@Composable

fun MyScreen() {

val entryPoint = rememberActivityEntryPoint<MyEntryPoint>()

val myInstance = entryPoint.myInstance

}
@ComposableScoped

class MyClass @Inject constructor() {

/
/
.
.
.


}

@InstallIn(ActivityComponent
:
:
class)

@EntryPoint

interface MyEntryPoint {

val myInstance: MyClass

}

@Composable

fun MyScreen() {

val entryPoint = rememberActivityEntryPoint<MyEntryPoint>()

val myInstance = entryPoint.myInstance

}
@ComposableScoped
@Scope

annotation class ComposableScoped
@Scope

annotation class ComposableScoped

@ComposableScoped

@DefineComponent(parent = ActivityComponent
:
:
class)

interface ComposableComponent_
@Scope

annotation class ComposableScoped

@ComposableScoped

@DefineComponent(parent = ActivityComponent
:
:
class)

interface ComposableComponent_

@DefineComponent.Builder

interface ComposableComponentBuilder {

fun build(): ComposableComponent

}
@Scope

annotation class ComposableScoped

@ComposableScoped

@DefineComponent(parent = ActivityComponent
:
:
class)

interface ComposableComponent_

@DefineComponent.Builder

interface ComposableComponentBuilder {

fun build(): ComposableComponent

}

@EntryPoint

@InstallIn(ActivityComponent
:
:
class)

interface ComposableComponentBuilderEntryPoint {

val componentBuilder: ComposableComponentBuilder

}_
@Composable

inline fun <reified T : Any> rememberComposableEntryPoint(): T {

val context = LocalContext.current

return remember {

val entryPoint = EntryPointAccessors.fromActivity(

context.getActivity(), ComposableComponentBuilderEntryPoint
:
:
class.java

)

EntryPoints.get(entryPoint.componentBuilder.build(), T
:
:
class.java)

}

}
@ComposableScoped

class MyClass @Inject constructor() {

/
/
.
.
.


}
@ComposableScoped

class MyClass @Inject constructor() {

/
/
.
.
.


}

@InstallIn(ComposableComponent
:
:
class)

@EntryPoint

interface MyEntryPoint {

val myInstance: MyClass

}
@ComposableScoped

class MyClass @Inject constructor() {

/
/
.
.
.


}

@InstallIn(ComposableComponent
:
:
class)

@EntryPoint

interface MyEntryPoint {

val myInstance: MyClass

}

@Composable

fun MyScreen() {

val entryPoint = rememberComposableEntryPoint<MyEntryPoint>()

val myInstance = entryPoint.myInstance

}
ViewModel
Are ViewModels


necessary


(or useful)


using Compose?
https://www.youtube.com/watch?v=rmv2ug-wW4U
val navController = rememberNavController()

NavHost(navController = navController) {

}_
val navController = rememberNavController()

NavHost(navController = navController, startDestination = "home") {

composable("home") {

HomeScreen()

}

}_
val navController = rememberNavController()

NavHost(navController = navController, startDestination = "home") {

composable("home") {

HomeScreen()

}

composable(

route = "detail/{id}",

arguments = listOf(navArgument("id") { type = IntType })

) {

DetailScreen()

}

}_
val navController = rememberNavController()

NavHost(navController = navController, startDestination = "home") {

composable("home") {

HomeScreen(onClick = { navController.navigate("detail/123") })

}

composable(

route = "detail/{id}",

arguments = listOf(navArgument("id") { type = IntType })

) {

DetailScreen()

}

}_
class DetailViewModel constructor(

) : ViewModel() {

}_
@HiltViewModel

class DetailViewModel @Inject constructor(

private val myUseCase: MyUseCase,

) : ViewModel() {

}_
@HiltViewModel

class DetailViewModel @Inject constructor(

private val myUseCase: MyUseCase,

savedStateHandle: SavedStateHandle

) : ViewModel() {

init {

val id = savedStateHandle.get<Int>("id")

}

}_
@HiltViewModel

class DetailViewModel @Inject constructor(

private val myUseCase: MyUseCase,

savedStateHandle: SavedStateHandle

) : ViewModel() {

init {

val id = savedStateHandle.get<Int>("id")

viewModelScope.launch {

myUseCase.suspendMethod(id)

}

}

}_
@HiltViewModel

class DetailViewModel @Inject constructor(

private val myUseCase: MyUseCase,

savedStateHandle: SavedStateHandle

) : ViewModel() {

var state by mutableStateOf("")

private set

init {

val id = savedStateHandle.get<Int>("id")

viewModelScope.launch {

state = myUseCase.suspendMethod(id)

}

}

}_
@Composable

fun DetailScreen() {

}_
@Composable

fun DetailScreen() {

val viewModel = hiltViewModel<DetailViewModel>()

}_
@Composable

fun DetailScreen() {

val viewModel = hiltViewModel<DetailViewModel>()

val stateConnectedToViewModelLifecycle = viewModel.state

}_
@Composable

fun DetailScreen() {

val viewModel = hiltViewModel<DetailViewModel>()

val stateConnectedToViewModelLifecycle = viewModel.state

val remembered = remember {

"executed again on configuration change and when navigating back"

}

}_
@Composable

fun DetailScreen() {

val viewModel = hiltViewModel<DetailViewModel>()

val stateConnectedToViewModelLifecycle = viewModel.state

val remembered = remember {

"executed again on configuration change and when navigating back"

}

val saveable = rememberSaveable {

"saved in a bundle"

}

}_
@Composable

fun DetailScreen() {

val viewModel = hiltViewModel<DetailViewModel>()

val stateConnectedToViewModelLifecycle = viewModel.state

val remembered = remember {

"executed again on configuration change and when navigating back"

}

val saveable = rememberSaveable {

"saved in a bundle"

}

LaunchedEffect(Unit) {

/
/
executed again on configuration change and when navigating back

}

}_
https://proandroiddev.com/viewmodels-using-compose-mutablestate
fl
ows-or-mutablestates-64d34ba548c5
Wrapping
up
Wrapping
up
unidirectional data
fl
ow
Wrapping
up
unidirectional data
fl
ow


screens instead of fragments
Wrapping
up
unidirectional data
fl
ow


screens instead of fragments


viewModels are still useful
Links
&
contacts
Architecting your Compose UI


developer.android.com/jetpack/compose/architecture


Jose Alcérreca - LiveData with SnackBar, Navigation and other events (the SingleLiveEvent case)


medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150


Michael Ferguson - Android SingleLiveEvent Redux with Kotlin Flow


proandroiddev.com/android-singleliveevent-redux-with-kotlin-flow-b755c70bb055


Lifecycle of composables


developer.android.com/jetpack/compose/lifecycle


Manuel Vivo - A Compose state of mind: Using Jetpack Compose's automatic state observation


www.youtube.com/watch?v=rmv2ug-wW4U


Fabio Collini - ViewModels using Compose: MutableStateFlows or MutableStates?


proandroiddev.com/viewmodels-using-compose-mutablestateflows-or-mutablestates-64d34ba548c5
@fabioCollini


linkedin.com/in/fabiocollini


github.com/fabioCollini


medium.com/@fabioCollini
THANKS
FOR YOUR
ATTENTION
QUESTIONS?
@fabioCollini

Contenu connexe

Tendances

Tendances (19)

Testing Android apps based on Dagger and RxJava
Testing Android apps based on Dagger and RxJavaTesting Android apps based on Dagger and RxJava
Testing Android apps based on Dagger and RxJava
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
 
droidparts
droidpartsdroidparts
droidparts
 
Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POP
 
Protocol-Oriented MVVM (extended edition)
Protocol-Oriented MVVM (extended edition)Protocol-Oriented MVVM (extended edition)
Protocol-Oriented MVVM (extended edition)
 
Practical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingPractical Protocol-Oriented-Programming
Practical Protocol-Oriented-Programming
 
Advanced javascript
Advanced javascriptAdvanced javascript
Advanced javascript
 
Practical Protocols with Associated Types
Practical Protocols with Associated TypesPractical Protocols with Associated Types
Practical Protocols with Associated Types
 
Reactive, component 그리고 angular2
Reactive, component 그리고  angular2Reactive, component 그리고  angular2
Reactive, component 그리고 angular2
 
Workshop 25: React Native - Components
Workshop 25: React Native - ComponentsWorkshop 25: React Native - Components
Workshop 25: React Native - Components
 
Angular2 + rxjs
Angular2 + rxjsAngular2 + rxjs
Angular2 + rxjs
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
 
Daggerate your code - Write your own annotation processor
Daggerate your code - Write your own annotation processorDaggerate your code - Write your own annotation processor
Daggerate your code - Write your own annotation processor
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
Protocol-Oriented MVVM
Protocol-Oriented MVVMProtocol-Oriented MVVM
Protocol-Oriented MVVM
 
Protocol Oriented MVVM - Auckland iOS Meetup
Protocol Oriented MVVM - Auckland iOS MeetupProtocol Oriented MVVM - Auckland iOS Meetup
Protocol Oriented MVVM - Auckland iOS Meetup
 
Typescript barcelona
Typescript barcelonaTypescript barcelona
Typescript barcelona
 
Reactive Programming with JavaScript
Reactive Programming with JavaScriptReactive Programming with JavaScript
Reactive Programming with JavaScript
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 

Similaire à Architectures in the compose world

Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development
Mahmoud Hamed Mahmoud
 
Property wrapper and how to use them with mvvm in swift ui i copy
Property wrapper and how to use them with mvvm in swift ui i copyProperty wrapper and how to use them with mvvm in swift ui i copy
Property wrapper and how to use them with mvvm in swift ui i copy
WannitaTolaema
 
Qtp Training Deepti 3 Of 44256
Qtp Training Deepti 3 Of 44256Qtp Training Deepti 3 Of 44256
Qtp Training Deepti 3 Of 44256
Azhar Satti
 
20150516 modern web_conf_tw
20150516 modern web_conf_tw20150516 modern web_conf_tw
20150516 modern web_conf_tw
Tse-Ching Ho
 
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdfCompose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
ssuserb6c2641
 

Similaire à Architectures in the compose world (20)

Flutter
FlutterFlutter
Flutter
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development
 
Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonf
 
Unit testing UIView
Unit testing UIViewUnit testing UIView
Unit testing UIView
 
iOS Talks 6: Unit Testing
iOS Talks 6: Unit TestingiOS Talks 6: Unit Testing
iOS Talks 6: Unit Testing
 
Property wrapper and how to use them with mvvm in swift ui i copy
Property wrapper and how to use them with mvvm in swift ui i copyProperty wrapper and how to use them with mvvm in swift ui i copy
Property wrapper and how to use them with mvvm in swift ui i copy
 
[22]Efficient and Testable MVVM pattern
[22]Efficient and Testable MVVM pattern[22]Efficient and Testable MVVM pattern
[22]Efficient and Testable MVVM pattern
 
KMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftKMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and Swift
 
Practialpop 160510130818
Practialpop 160510130818Practialpop 160510130818
Practialpop 160510130818
 
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in Swift
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in SwiftMCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in Swift
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in Swift
 
Qtp Training Deepti 3 Of 44256
Qtp Training Deepti 3 Of 44256Qtp Training Deepti 3 Of 44256
Qtp Training Deepti 3 Of 44256
 
Qtp Training
Qtp Training Qtp Training
Qtp Training
 
Migrating Objective-C to Swift
Migrating Objective-C to SwiftMigrating Objective-C to Swift
Migrating Objective-C to Swift
 
20150516 modern web_conf_tw
20150516 modern web_conf_tw20150516 modern web_conf_tw
20150516 modern web_conf_tw
 
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdfCompose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
 
Using Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationUsing Reflections and Automatic Code Generation
Using Reflections and Automatic Code Generation
 
Protocol-Oriented Programming in Swift
Protocol-Oriented Programming in SwiftProtocol-Oriented Programming in Swift
Protocol-Oriented Programming in Swift
 
303 TANSTAAFL: Using Open Source iPhone UI Code
303 TANSTAAFL: Using Open Source iPhone UI Code303 TANSTAAFL: Using Open Source iPhone UI Code
303 TANSTAAFL: Using Open Source iPhone UI Code
 
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
 
MBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&CoMBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&Co
 

Plus de Fabio Collini

Plus de Fabio Collini (17)

Using Dagger in a Clean Architecture project
Using Dagger in a Clean Architecture projectUsing Dagger in a Clean Architecture project
Using Dagger in a Clean Architecture project
 
SOLID principles in practice: the Clean Architecture - Devfest Emila Romagna
SOLID principles in practice: the Clean Architecture - Devfest Emila RomagnaSOLID principles in practice: the Clean Architecture - Devfest Emila Romagna
SOLID principles in practice: the Clean Architecture - Devfest Emila Romagna
 
SOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean ArchitectureSOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean Architecture
 
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFrom Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
 
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night TurinAsync code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
 
Recap Google I/O 2018
Recap Google I/O 2018Recap Google I/O 2018
Recap Google I/O 2018
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
 
From java to kotlin beyond alt+shift+cmd+k
From java to kotlin beyond alt+shift+cmd+kFrom java to kotlin beyond alt+shift+cmd+k
From java to kotlin beyond alt+shift+cmd+k
 
Android Data Binding in action using MVVM pattern - droidconUK
Android Data Binding in action using MVVM pattern - droidconUKAndroid Data Binding in action using MVVM pattern - droidconUK
Android Data Binding in action using MVVM pattern - droidconUK
 
Data Binding in Action using MVVM pattern
Data Binding in Action using MVVM patternData Binding in Action using MVVM pattern
Data Binding in Action using MVVM pattern
 
Android Wear CodeLab - GDG Firenze
Android Wear CodeLab - GDG FirenzeAndroid Wear CodeLab - GDG Firenze
Android Wear CodeLab - GDG Firenze
 
Testable Android Apps using data binding and MVVM
Testable Android Apps using data binding and MVVMTestable Android Apps using data binding and MVVM
Testable Android Apps using data binding and MVVM
 
Introduction to Retrofit and RxJava
Introduction to Retrofit and RxJavaIntroduction to Retrofit and RxJava
Introduction to Retrofit and RxJava
 
Testable Android Apps DroidCon Italy 2015
Testable Android Apps DroidCon Italy 2015Testable Android Apps DroidCon Italy 2015
Testable Android Apps DroidCon Italy 2015
 
Clean android code - Droidcon Italiy 2014
Clean android code - Droidcon Italiy 2014Clean android code - Droidcon Italiy 2014
Clean android code - Droidcon Italiy 2014
 
Librerie su Android: come non reinventare la ruota @ whymca 2012
Librerie su Android: come non reinventare la ruota @ whymca 2012 Librerie su Android: come non reinventare la ruota @ whymca 2012
Librerie su Android: come non reinventare la ruota @ whymca 2012
 
Android Widget @ whymca 2011
Android Widget @ whymca 2011Android Widget @ whymca 2011
Android Widget @ whymca 2011
 

Dernier

%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 

Dernier (20)

%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 

Architectures in the compose world