Loading...
Home
  • Tech Blogs
  • Videos
  • Conferences
    • Droidcon News
    • Upcoming Conferences
    • Become a Partner
    • Past Events
    • Keep Me Informed
    • Diversity Scholarships
  • Community
    • droidcon Team
    • How to Hold a Droidcon
  • Android Careers
Sign In

Global CSS

droidcon News
 

droidcon San Francisco 2019

Share
Tweet

 

Next Generation Android UI with Jetpack Compose
By
Pedro Veloso
droidcon San Francisco 2019
Android Widgets have been in existence since the very first version of Android. Since Android 1.0 and now, mobile UI paradigms and application needs have changed dramatically. There have been great solutions that leverage the existing UI widgets and improve them, such as Jetpack (Support Libraries) for backwards compatible support and Data Binding for bringing state and UI closer together. Though they served us well, the new Kotlin-first approach by Google allow us to imagine what a modern UI framework would look like. Idiomatic, Kotlin-first, with retro-compatibility from the get go and support for live-previews, Jetpack Compose is Google's new experimental way of tackling Android's UI, built from the ground up without any dependence on pre-existing Android Widgets. This talk will offer a hand-on approach on building a material looking application with Jetpack Compose, by using its existing components.
Transcript
English
00:00
[Music]
00:12
so hello everyone my name is Pedro I
00:16
work at button in NYC and that's my
00:21
Twitter and Instagram and all people
00:24
don't usually put their Instagram but I
00:26
put there so I can get more followers
00:27
and you know pretend that I'm cool
00:31
and today I'm going to be talking about
00:35
jetpack Campos this is going to be a
00:39
very practical talk so the essence of it
00:45
is if you were to take jetpack compose
00:48
as it is today and try to use it for
00:51
building a project how would that look
00:52
like and that's the essence of this
00:55
presentation I'll leave a big sort of
01:02
note like warning up front which is you
01:05
shouldn't try to use jetpack compose for
01:08
production projects right now this is
01:11
mostly for you know kind of an exercise
01:15
to to see how it looks and how it works
01:19
but I believe the current version of
01:22
jetpack compose is zero dot one dot 0
01:24
slash they have something like that so
01:26
it's definitely marked for not
01:28
production-ready
01:30
the API changes very frequently so it's
01:34
and there's a lot of things that are
01:36
actually missing
01:37
as you'll see so what is jetpack impose
01:43
it simplifies and accelerates UI
01:47
development on Android quickly bring
01:49
your app to life with less code powerful
01:52
tools and intuitive Kotlin ap ice so I
01:56
think that's pretty clear what it is
01:57
right perhaps a better question is why
02:05
do we need jetpack compose you know some
02:08
may argue that you know views nowadays
02:11
are actually much easier we have
02:12
constraint layout
02:13
we have data-binding or going for a few
02:16
binding now there's a bunch of other
02:18
things why do we need it so let's start
02:22
by talking about inheritance which is
02:25
how the current view system operates so
02:32
in the beginning there was the view and
02:35
it was good you know when he came around
02:38
he had like a lot of things built in
02:41
there that the Android UI team thought
02:46
you know these are the things that are
02:47
going to be fundamental to pretty much
02:49
every element on the screen so we're
02:51
gonna bake it into these one class and
02:54
everything is gonna descend from it one
02:57
thing to notice is for example like
02:59
there's focus control in there
03:02
why because back back when Android came
03:05
around the things that resembled
03:08
smartphones at the time usually had
03:10
joysticks and you'd use this joystick to
03:12
select things so you know they thought
03:14
you know this is gonna be something that
03:16
cell phones that smart phones that for
03:18
sure you know we're gonna have a
03:18
joystick to select things and know
03:21
didn't turn out to be quite that way so
03:24
at the end of the day this class does a
03:26
lot of the sizing calculations the as
03:30
all the things in there for the padding
03:33
and margin all those things put together
03:35
amounts to twenty seven thousand lines
03:39
of code in this one class then we have
03:44
the text view which descends from the
03:46
view and adds a bunch of other stuff
03:51
like takes care of text rendering he
03:55
also has everything that you need for
03:56
text selection and all the things
03:59
related to font he also has support for
04:02
drawables you can have a drawable around
04:04
text so all in all the textview is
04:08
twelve thousand lines of code and if you
04:11
consider that it is sent directly from
04:13
view it's basically 12 + 27 right then
04:20
you have button
04:21
that the sense from textview now this is
04:26
where it starts to get tricky with
04:28
inheritance that you don't really want
04:31
to have a button with all the properties
04:32
of the text view because when a text
04:34
view is made to have selectable text and
04:36
you don't want your buttons typically -
04:38
I have selectable text so you have to
04:39
start selectively disabling things from
04:44
the classes you're inheriting
04:45
and you can see that this doesn't scale
04:47
very well and this is exactly the reason
04:50
that if you want to on a button on
04:52
Android you can make the text being
04:54
selectable and then you have checkbox
04:59
which really is just a specialized
05:02
version of button which is a specialized
05:04
version of textview so in a checkbox you
05:07
have added state for being checked or
05:09
not it uses the drawable from the
05:12
textview to have that check mark that
05:14
you know and it kind of plays around to
05:19
not do exactly the same sort of things
05:21
that button does
05:23
so yeah it's this design is definitely
05:26
not ideal and these things have been in
05:30
existence since Android 1.2
05:34
you can imagine that whenever one
05:36
developer probably has to change 100
05:38
code in view it's probably gonna be
05:41
sweating and afraid of doing so because
05:43
just the impact that this this thing has
05:48
okay next and there were a lot of talks
05:51
at joy Con this year about this problem
05:55
which is managing state anyway you know
05:59
and that's why a lot of things came into
06:02
existence like adopting the reactive
06:05
patterns different types of
06:07
architectures essentially the problem is
06:10
that the UI and the thing that has the Y
06:14
definition and the thing that actually
06:17
modifies and should contain the state
06:21
are completely separate it for example
06:26
is very easy for you to add a view in a
06:28
layout and forget to actually update its
06:31
State on your activity you have to
06:32
actually go there and you know inflated
06:35
and change the value of it so those two
06:38
things are not directly related and this
06:40
brings a lot of problems and that's why
06:42
we have a lot of libraries around these
06:44
to make that easy to manage another way
06:54
that compose is distinct from the
06:58
current views is that it is not bundled
06:60
with the SDK so it's going to be just
07:03
another library that you consume so it's
07:07
entirely up to you to include including
07:12
in your project and include whatever
07:14
version of it that that you see fit and
07:17
of course this brings a lot of vintages
07:19
one of them being that you get
07:21
consistent look across devices so you're
07:25
not you're not dependent on Android
07:26
versions or the manufacturer anymore the
07:32
other thing is because it's being built
07:33
right now it's built with materials
07:36
design from from the start whereas in
07:40
the views you know if you really want to
07:42
preserve all of those things you have to
07:45
include the material libraries the the
07:47
jetpack libraries and a bunch of other
07:49
things just to get like this thing to be
07:51
exactly the same across the board for
07:55
all the versions of Android you support
07:59
so now that we see why we might need
08:02
something like compose how do we use
08:04
this this is what we're going to be
08:09
building today so it's a simple weather
08:13
app that displays the current
08:16
temperature the minimum in the max yes
08:19
some iconography in there as a
08:20
background you can see it vaguely looks
08:24
material and there's also two screens
08:27
that the user navigates back and forth
08:30
the second screen having a list of the
08:34
forecast for the coming days so let's
08:38
start with the basics layouts first one
08:42
it's column and as you can imagine this
08:45
is just something that will layout is
08:47
children
08:48
vertically one thing to remember is in
08:54
compose you should be have present this
08:60
idea of the main axis so in a column the
09:03
main axis or in whatever component the
09:05
main axis is the axis of the direction
09:08
that it lays out its items and there's
09:10
going to be relevant as we go as we go
09:12
forward similarly we have the row which
09:16
lays out these children
09:17
horizontally and for the road the main
09:20
axis would be the horizontal axis and
09:24
conversely you would have a cross axis
09:27
which is the opposite of the main axis
09:31
on those two next thing I'll talk about
09:39
is a specialized type of column and you
09:44
can imagine that the same thing exists
09:45
for four row as this concept of flex in
09:51
compose so what it does is it adds the
09:55
ability to distribute the its children
10:02
according to percentages so on this
10:06
element a here and I'm doing that
10:09
through a function called inflexible and
10:13
a is just the content that you see on
10:16
the window what it is doing essentially
10:20
it sort of like a wrap content is saying
10:23
just accommodate the content of a let it
10:27
take as much space as it needs and no
10:29
more than that and if you use something
10:34
like expanded and pass it the Flex value
10:36
in this example you have B and C what
10:39
we're saying is for being C use the
10:42
remaining real estate and use 40 and 60
10:45
percent of that remaining real estate
10:47
accordingly then we have some basic
10:52
elements that we're going to need to
10:53
build this screen and these are pretty
10:56
much self-explanatory so text is just
10:58
draw text image then we have card for
11:01
actually drawing
11:02
cardview that you know from for material
11:05
there's a couple of other things like
11:07
the spacers and there's like two
11:09
specialized ones and that's just things
11:11
to create empty space in between
11:13
elements and I added the number of lines
11:18
of code that each of these classes has
11:21
so you can just compare with how it was
11:24
in in the view in the current view
11:27
system and you can see it's like a very
11:29
small number of lines of code and the
11:33
reason for that is because they don't
11:35
have more than what they need if you
11:37
need to add padding or margin all those
11:39
things those are going to be composable
11:41
functions that you apply to these things
11:44
and they're not part of them I wanted to
11:50
introduce the slide here so this is how
11:51
the definition of the text composable
11:57
function looks like starting at the top
12:00
one thing to call out is that you have
12:02
this annotation at composable and this
12:06
is not a Java annotation as you know
12:08
them so this is actually an annotation
12:10
for the compiler for the Kotlin compiler
12:14
plug-in system and that's which is
12:17
something that requires some changes and
12:19
that's part of the reason why to use
12:21
compose currently you need to use the
12:24
canary version of Android studio and a
12:26
specific version of of Kotlin the other
12:32
thing you'll notice is that composable
12:35
functions start with a capitalized
12:38
letter so that text there starts with a
12:41
capitalized letter and the other thing
12:44
in this is something that you'll see a
12:47
lot in the current state is you'll have
12:50
a lot of to do's and this kind of you
12:53
know reiterates on the fact that this
12:55
thing is not production ready is still a
12:57
lot of kind of stuff they need to fall
13:01
in place before this is even in alpha
13:05
stage
13:09
so now we will learn about some of the
13:11
core components how do we actually put
13:14
these things together so let's start
13:18
with the background on your activity you
13:22
have the oncreate method which is where
13:24
you typically inflate your layout in
13:27
compose you have this set content
13:30
function and there I call him something
13:34
another function and you can tell it's a
13:37
composable function because it starts
13:38
with a capitalized letter this one is
13:41
called material theme and I'll go into
13:43
more detail about this but for now just
13:45
thing this is the thing that actually
13:46
applies material theming to everything
13:48
that's inside it and then I call
13:50
something called main screen which is
13:51
something I defined and this is main
13:54
screen so again notice that this
13:57
function that I'm writing I annotate it
13:59
with composable and then I need actually
14:04
something to lay out the children so I
14:07
create a column and I create another
14:09
method another function called draw
14:13
background and draw background looks
14:16
like this and notice that the difference
14:19
here is that we have this draw image
14:22
where to the attribute of image I Pass
14:26
Plus image resource and then the
14:29
qualified resource for the drawable
14:31
which is the Golden Gate Bridge that you
14:34
see there the syntax for this is gonna
14:37
change so it's kind of weird to think
14:40
about like equals plus I believe this
14:43
might have already changed not sure so
14:45
compose is changing really fast right
14:47
now this is just synthetic sugar if at
14:55
this point you stop and look into the
14:58
layout inspector you're gonna see
15:01
something like this this I'm not sure if
15:03
it's read about but it says like Android
15:05
compose view and from this point on as
15:10
many things that you add to your compost
15:12
layout this is how the layout inspector
15:16
all the layout inspector is gonna show
15:18
you right now because everything falls
15:19
inside of these Android compose view the
15:21
reason is because
15:22
lay off inspector is not ready for
15:24
compose yet so it cannot actually
15:26
determine what is in there and show you
15:28
so this is just to show you that some of
15:31
the tools are still kind of catching up
15:33
to this so we need to define some data
15:36
models this is just plain Kotlin just
15:39
first to have some context as we go
15:40
forward so I define something called
15:42
current weather which has a location
15:45
temperature type and weather forecast
15:48
temperature is just something that has
15:50
temperature is Celsius then we have a
15:54
weather forecast which has a minimum
15:55
maximum and a weather state and state is
15:60
an enum class there's like sunny rainy
16:02
so on and so forth and he has a drawable
16:05
and a string and if you're curious like
16:07
that's what is inside the resources for
16:11
those things so with those models that I
16:24
shown how would I actually use them you
16:26
pass them as an argument and I'm
16:29
creating this title composable function
16:35
and you notice this is where I'm doing
16:38
I'm using text as we seen before and
16:41
this is where I'm actually assigning the
16:44
value contained in it and here I place
16:47
some styling to the text and to unfold
16:51
this a little bit h2 is defined in the
16:56
material specs so it means like other
16:58
size too
16:59
and because I didn't change anything by
17:01
default it comes as black which didn't
17:04
work very well on that background so
17:06
what I did is I use the copy the copy
17:10
function on the Cotton's data class to
17:15
create a copy of the style but change
17:17
the property for color and this is kind
17:21
of a good segue into how timing works
17:23
it's actually very simple you have this
17:27
thing called material colors so you just
17:29
define your own variable and
17:31
you override the ones that the
17:34
properties that you want to use and
17:36
these maps directly to the material spec
17:38
and conversely us something called
17:42
material topography which you can define
17:45
the specific style for each each of
17:48
those h1 h2 so on and so forth
17:51
notice that this actually is not an
17:53
extensive list and even like textile as
17:57
many other properties I already
17:59
for example supports different fonts
18:02
with a font family and then as you
18:05
specify different point font weights it
18:07
can pick up smartly if we choose the
18:10
thin version instead of the regular or
18:12
the bold etc but this is just for the
18:15
sake of example so with those two
18:20
variables defined I go back to our set
18:24
content and on material team I just
18:28
apply those two variables and since I
18:31
did that I cannot simplify my title
18:35
function to strip the part where I
18:37
actually change the color for h2 because
18:40
I did that on my style now let's try to
18:46
make this look centered like we see it
18:49
there so if you remember because this is
18:52
the column if we want to Center things
18:54
horizontally that would not be its main
18:57
axis but its cross axis so on the column
18:60
property we use on the column function
19:05
we use the cross axis alignment and
19:07
assign it to Center and that would
19:09
Center that title and then for title
19:14
itself to have some space between the
19:17
top of the screen and the text we use
19:20
the ID spacer now for doing the the
19:30
weather State as you see there there's
19:32
that icon and says partially cloudy we
19:36
can use a robe and I use two types of
19:41
centering because I wanted the text
19:45
to be in the middle of the icon and for
19:48
them to be in the center of the screen
19:50
as well then we have something called
19:52
contain there's just something that
19:54
limits the size of the image to a
19:56
specific dimension and we're just using
19:58
the image resource like we had before we
20:02
add some space in between the icon and
20:05
the text and finally just a little extra
20:10
there we changed the Alpha value of the
20:13
text so it doesn't call out so much
20:17
attention for aesthetics now we're
20:25
building like the rest of the current
20:29
the current weather for the day and this
20:34
will would be done with exactly the same
20:36
things that we described so far so I'm
20:39
gonna kind of skip the details of those
20:41
what I'm more interested here is to
20:44
point out that because this is just code
20:48
this entire block that you see there so
20:53
both on the left and on the right you
20:55
can start to use things that you know
20:57
from clean code practices so I don't
21:01
have to have all the you know the whole
21:04
blotter code there and you can actually
21:05
start to write these things very
21:06
elegantly where you just define you know
21:09
whether state current temperature a min
21:11
and Max you can easily reuse them and
21:14
the code becomes very very readable and
21:16
concise then I would use flex column to
21:22
actually space these items around and
21:26
because I kept them in separate
21:29
composable functions this snippet here
21:33
actually just deals with with layouting
21:38
the various blocks and not the actual
21:40
rendering of each specific block I don't
21:47
know if you remember from that video
21:48
that played initially but on the second
21:50
screen we have this list of the
21:53
forecasts so now let's see how we would
21:56
build that
21:58
and this is what we're building right
21:59
now that weather forecast row which is
22:02
our single list elements we would use a
22:07
flex row which is similar to a flex
22:09
column but in this case is like
22:10
something that lays out items
22:13
horizontally and reduce everything that
22:16
we use before to build that view you can
22:18
probably imagine how it would be built
22:20
by now what I'm more interested in
22:22
showing is to actually do the card
22:24
layout we would use something called
22:26
card as you see in there and I
22:29
overloaded the background color to make
22:31
it transparent I gave it some elevation
22:33
I'm not sure if it is you can tell on
22:37
this screenshot but it does have some
22:40
shadow in there
22:41
and then I'm also adding the padding and
22:43
this is the first time we actually seen
22:46
this being define that padding is
22:49
separating the content from the edges of
22:53
the cards so giving it a little bit of
22:55
buffer so it looks good
22:58
and this is how you can see that padding
23:00
is actually not something that belongs
23:01
to card or to text or anything like that
23:03
is it's a composable function that's
23:07
outside of that realm so now we have an
23:11
item and how would you make a list of
23:13
items well you just use a for loop and
23:16
that's it there's a little bit more
23:22
things involved if you want to make a
23:24
scrollable list of items namely going
23:29
back to our Flex column and this is
23:31
already the second screen and I'm just
23:35
reusing that draw background and title
23:36
that we define before because there's
23:38
just functions and we can make them
23:40
public and reuse them anywhere so it's
23:42
very easy to reuse components that you'd
23:43
find from one screen to the other and
23:48
for the list in question I the four
23:52
would be contained within that weather
23:53
forecast list then we apply that
23:57
vertical scroller and that's the thing
23:59
that actually makes it scrollable so one
24:02
thing to notice here is that if you have
24:06
10,000 elements right now you would
24:08
actually inflate those well not inflate
24:11
but
24:12
actually process those 10,000 elements
24:14
the first time right there's not yet as
24:18
far as I can tell any sort of like lazy
24:19
loading
24:20
I think the pattern for view older
24:23
flyweight pattern is gonna go away for
24:25
compose probably because it just doesn't
24:27
make sense but probably something like
24:30
lazy loading will come into place so you
24:33
don't have to actually render all of
24:36
those things ahead of time
24:39
one thing that compose does however is
24:42
if say that 10,000 list of elements only
24:48
one of them changes actually composed
24:51
only execute the code for changing that
24:53
specific one and that has to do with the
24:55
structure it uses underneath so we
24:59
actually only validates that specific
25:01
one and doesn't have to process the
25:02
whole list so how can you navigate
25:08
between screens and this is where I
25:09
actually have to come up with sort of my
25:14
own way of doing it because there's you
25:16
know there's no documentation all there
25:17
is is basically just source code that
25:20
you can browse and figure figure it out
25:23
but I wanted to do it in a way that I
25:26
could have one activity and change
25:30
between screens because it's something
25:32
that we you know are moving towards so
25:34
we can avoid all the intricacies of
25:36
dealing with the activity lifecycle so
25:40
the way I did it is I define this silk
25:45
last screen where I created two objects
25:50
for each of my screens and then we have
25:56
something that has this model annotation
26:00
and what that does is a specific compose
26:05
annotation that tells that the
26:07
properties of these clasps are
26:11
observable so as they are passed through
26:13
your composable functions if one of the
26:16
values changes then compose knows how to
26:19
rerender the specific section that uses
26:21
that variable or that property and
26:25
I'm making it an object so I can have
26:28
this state be shared between screens so
26:32
if I would change that current screen
26:34
there and if I'm passing this along then
26:37
whatever part of the composable code
26:39
deals with the current screen variable
26:41
would get called with a new value and
26:45
then I just created a convenient
26:48
function call navigate to which you pass
26:50
the screen and all it does is under the
26:52
hood it changes that current screen like
26:54
I described and this is how he actually
27:02
works so we go back to our set content I
27:05
apply something called crossfade which
27:08
is something that Campos has that will
27:12
fade between the previous state and the
27:15
new state of whatever child elements it
27:19
has so in this case if you apply it to
27:21
an entire screen you'll see that the
27:23
screen crossfade is from one to the
27:24
other and then all I have is a one
27:27
condition for screen and I say you know
27:30
if if it is of type main then execute
27:34
this function main screen otherwise it's
27:37
get the other one
27:40
so I overridden I overrode the on back
27:46
pressed so I could have back navigation
27:48
from the second screen to the first one
27:50
mm-hmm
27:51
and all these works is I see if I'm on
27:54
the second screen which is the weather
27:55
forecast screen if I am I just call that
27:58
navigate to which under the hood changes
28:00
the value of current screen then that
28:04
cross faith will be called again and
28:08
that's how the screen will actually
28:10
change otherwise I'll just let super on
28:14
back press be cold because that means
28:16
we're in the first screen we'll just
28:17
want to exit the app and at the end of
28:21
the screen we have a button to go to the
28:23
second screen and all we have to do is
28:27
you know define the string there and on
28:31
click we just call navigate to and the
28:34
screen that we want to go and that's all
28:37
you need
28:46
and that's all I have okay any questions
29:07
so the question is if I see difference
29:09
in performance between recyclerview and
29:11
this I didn't test for that I don't know
29:17
exactly how I would test for that I mean
29:19
I guess you would have to perform it
29:21
profile at this code which could be a
29:24
bit tricky to compare views we
29:27
composable functions I guess for
29:30
profiling I'll kind of wait for Google
29:32
to come up with some way of profiling
29:35
composed before I try to make any sort
29:39
of comparison oh that that has to do
29:44
with the video only yeah so actually yes
29:48
so the app and I'll post afterwards I'll
29:52
post the code in a github I'll do some
29:56
cleaning up and posted on Gita when you
29:57
you guys can test it and yeah so the way
30:11
I understand it resource loading on
30:14
compose is going to be a synchronous and
30:16
agnostic of content so my expectation is
30:20
that you're gonna have that draw image
30:22
and you can pass whatever you want to it
30:24
you could be a resource you could be or
30:25
URL
30:26
it could be something inside a database
30:28
and it just knows what to do and how to
30:31
load it as synchronously if you look at
30:34
the code there is already some
30:35
synchronicity in there but not all of it
30:37
and I believe there's even talks on the
30:41
selection all about using co-routines
30:43
under the hood for doing some of that
30:45
heavy lifting
30:58
yeah I don't I don't have the number but
31:00
I do think that actually compose is
31:03
smaller than if you had jetpack support
31:06
well support libraries and the material
31:08
team in all those things so actually I
31:10
think is an advantage yeah I didn't
31:31
expect it but I would imagine it's some
31:33
sort of like surface of canvas and yes
31:35
it would be a view because the layout
31:38
inspector is looking at it right the one
31:41
thing that I didn't talk here like the
31:43
app bar is actually a composable
31:45
function I didn't show because I just
31:47
you know there's only so much I could
31:49
feed here but for the decorations on
31:51
Android I still have to rely on the old
31:54
view system so just overload the styles
31:58
for that and apply the team through the
32:02
manifest so it's still a mix that you
32:04
have to do between the two yes yeah so
32:13
crossfade is one of them I think it
32:17
builds upon other things that are in
32:19
there already the crossfade I believe I
32:24
saw yeah mostly fade out and fade in I
32:28
didn't see any movement but I but I do
32:33
believe there is movement because Google
32:37
as a demo app called jet News and he has
32:40
this drawer that animates to open and
32:44
close so and it's probably worth taking
32:47
a look
33:03
Oh
33:08
so what's the most important thing that
33:11
it is missing right now well I would say
33:14
the commentation is one of them because
33:16
I had to do a lot of wild guesses well
33:18
doing this which is a good and a bad
33:21
thing but I mean we gotten used to
33:23
Google being a bit more opinionated
33:25
nowadays and I hope they are a bit more
33:28
opinionated and the other one would be
33:30
tooling so as you can imagine everything
33:32
that you have for testing you're wise
33:33
from expresso appium those things don't
33:36
work with this right so that's another
33:39
reason why this is not production ready
33:40
I mean unless you want to just do like
33:42
your own project on the side for fun
33:45
because you couldn't test this with any
33:48
of the tools that you have right now
33:54
over flutter that's a good question
34:09
well I guess flutter you have to use
34:12
Dart
34:13
right so that's probably one reason and
34:21
the art brings a lot of overhead with
34:25
the libraries that he has where compose
34:27
might be smaller it's probably other
34:34
reasons but I guess if you're I would
34:40
expect composed to be more performant
34:44
going forward for Android and more
34:46
reliable than flutter but I said I don't
34:49
have experience with flutter so this is
34:51
this is mainly based on what I've seen
34:54
from other people
35:04
if that's it thank you very much
35:08
[Applause]
35:11
you
droidcon News

Tech Showcases,

Developer Resources &

Partners

/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/home-details/EmployerBrandingHeader
EmployerBrandingHeader
https://jobs.droidcon.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/jobs-droidcon/jobs.droidcon.com
jobs.droidcon.com

Latest Android Jobs

http://www.kotlinweekly.net/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/kotlin-weekly/Kotlin Weekly
Kotlin Weekly

Your weekly dose of Kotlin

https://proandroiddev.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/pad/ProAndroidDev
ProAndroidDev

Android Tech Blogs, Case Studies and Step-by-Step Coding

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
Zalando

Meet one of Berlin's top employers

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
Academy for App Success

Google Play resources tailored for the global droidcon community

Follow us

Team droidcon

Get in touch with us

Write us an Email

 

 

Quicklinks

> Code of Conduct

> Terms and Conditions

> How to hold a conference

> FAQs

> Imprint

Droidcon is a registered trademark of Mobile Seasons GmbH Copyright © 2020. All rights reserved.

powered by Breakpoint One