00:03
welcome welcome everyone to droidcon
00:06
online this is our first of our series
00:08
this is the first of our jetpack series
00:10
and the first uh webinar
00:12
that we're offering is part of a larger
00:14
droid con online series with
00:16
with four major series in in the works
00:18
right now we'll have
00:19
uh building upon this uh series here on
00:22
jetpack we'll have two more
00:24
uh coming online to cover many more of
00:26
other exciting things
00:27
jetpack our next series which i'll tease
00:30
a little bit uh with another slide here
00:33
uh advanced kotlin series we have a
00:37
a series of events coming up where we'll
00:39
cover a flutter kotlin multi-platform
00:41
and then we have something
00:43
that we're calling hands-on and in-depth
00:44
and that's kind of our
00:46
catch-all topic where we're going to
00:49
hands-on doing hands-on coding together
00:53
lots of uh joint work together with with
00:55
the audience with the speaker and we're
00:57
going to present a lot of exciting
00:59
so we're really happy to have everyone
01:03
i want to introduce our speakers they're
01:05
still live in the cameras you should be
01:06
able to see everybody
01:08
our first speaker today is going to be
01:11
developer evangelist from twilo talking
01:14
about jet packs for you and i we figured
01:16
that mark would be great to kick this
01:18
he's really going to be talking a lot
01:21
we can do and it's a good overview i
01:24
think for us to dive into these topics
01:26
and then with divya
01:27
getting more specific into camera x and
01:29
then we're happy to have brian gardner
01:32
uh a developer and instructor from big
01:34
nerd ranch as well talking about how to
01:36
become a composer using jetpack compose
01:38
so uh we're we're going to get into this
01:40
real quick because you're here to hear
01:43
a couple of housekeeping issues love for
01:46
everybody who's joined us
01:48
to go over to slido.com and put in the
01:54
the reason we're doing this is because
01:56
we have so many people joining that it's
01:58
going to be impossible during the
01:59
10 minutes q a that we have for each
02:03
to filter through the questions
02:05
slido.com will give you the ability
02:07
to post your question there and you'll
02:10
be able to very quickly see
02:11
if somebody else is asking the same
02:13
question if they are asking the same
02:16
vote give it a thumbs up vote on it and
02:18
what we will do at the end
02:20
is filter through the questions that
02:22
receive the most votes where we think
02:24
urgency is and we will try to answer
02:26
those in the time allotted
02:28
uh if our speakers have time and stick
02:30
around after we can try to answer
02:31
questions but we're going to be able to
02:33
we want to stick pretty pretty closely
02:35
to that 10 minute time period so we're
02:36
going to try to get
02:37
the best uh and most frequently asked
02:41
please take a minute also in your chat
02:43
window if you miss it because i'm going
02:46
uh uli one of our co-organizers here
02:48
today is going to send a link
02:50
and you should see that in your chat
02:51
window or your question window on your
02:53
interface as well so you can directly
02:56
the q a portion for this event
02:59
the question that comes up we will have
03:02
from this particular webinar online and
03:05
archive by tomorrow at droidcom.com
03:08
and also transcripted so you'll be able
03:09
to get audio transcription
03:12
as well with your video that will also
03:14
be indexed and searchable
03:15
on droidcom.com to quickly
03:19
quickly tease what's coming up uh next
03:21
week on the 30th we have uh on april
03:24
30th our advanced kotlin series with ash
03:26
davies dmitry sitnikov and surosha
03:29
uh and we're kicking it off as well with
03:32
an overview and refactors
03:33
refactoring legacy code with colin and
03:35
then diving into some more specific
03:38
so we would love for all of you joining
03:40
us today to see you again on the 30th
03:43
uh for that as well so without further
03:46
ado that's that's it for me
03:47
i'm going to turn the time over to
03:49
marcos and uh divvy and brian are going
03:51
to shut off their cameras i will as well
03:54
and we'll have uh we'll put marco here
03:58
and uh and he can he can take it away
04:10
okay marco you should be ready to go
04:12
you're the presenter now
04:14
yeah uh just getting just getting there
04:24
all right you should all be seeing my uh
04:29
android studio screen here uh i am just
04:32
my slides because that's what you want
04:35
uh so yeah hello everyone my name is
04:39
and i serve the developer evangelism
04:43
at twilio um i have been a developer
04:47
i have been an android developer for
04:50
you know i know you know where to find
04:52
me on the internet but i just wanted to
04:54
make sure there's some information about
04:56
in here also some information about
04:58
twitter twitter is a company i work for
04:60
uh if you don't know twilio twilio is a
05:03
communications platform
05:04
that helps uh developers like you and i
05:08
add communications into your application
05:10
such as like text messages chat
05:15
anything to do with communications here
05:18
used twilio in the past but you don't
05:20
know if you've used something like lyft
05:22
or airbnb for example it's all using
05:25
twitter on the back end but that's
05:27
enough about twilio um
05:29
i wanted to also let you know i am on
05:32
uh and i am very very passionate about
05:34
this thing uh called jetpack
05:36
which is uh what i'm going to be telling
05:40
uh but i want to start like very very
05:42
slow here and i want to start by telling
05:45
okay so this is uh the story of
05:48
the year 2017 and uh because we're
05:53
uh i kind of want to change the slides
05:55
and say this was a long long time ago
05:58
uh 2017 because we're talking about tech
06:01
uh back in 2017 uh there was
06:04
here i was writing code just like this
06:08
so i was getting my instant state just
06:11
and i imagine that if i could ask for
06:14
some of you to like raise your hand
06:16
you would say yeah i still do things
06:20
the other thing that i was doing is i
06:22
was also building uh
06:23
camera applications back then uh and
06:27
ask you to raise your hands i'm sure you
06:28
would say yeah i'm building camera
06:31
or i i used to build some camera
06:34
and like just to just to kind of uh get
06:39
i uh when it comes to camera
06:41
applications for example
06:42
i think um you've all you've all seen
06:46
something like this okay because
06:47
building a camera application is super
06:50
right now uh well it used to be like
06:52
super easy uh it's easier now but it
06:54
used to be super easy because
06:55
building a camera application basically
06:57
means well you create the camera manager
06:59
then you set up the camera id then you
07:01
up the camera output then you set the
07:03
transformation matrix so it's extra view
07:05
and then you start a background threads
07:06
then you open a connection to the camera
07:09
and then you set up the image buffer
07:11
size of text review then you start the
07:13
and then you start the camera preview
07:17
that's easy right does anyone else here
07:21
get a mild anxiety yeah i'm sure if you
07:23
could raise your hand your words
07:24
i'm sure you can if you could you know
07:26
drink some conference water
07:28
right now you would uh and yeah so
07:30
that's the kind of thing i used to deal
07:32
okay and then came uh google i o 2017 so
07:38
talking about old markers there uh
07:41
everything changed because beta gluo
07:44
2017 they announced
07:46
the architecture components so back then
07:49
architectural components was the name of
07:51
uh which later just came to be part
07:54
of the jetpack the jetpack
07:57
uh family and i remember listening to my
08:01
and uh my clarion talks like
08:03
specifically about jetpack compo uh
08:05
architecture components
08:07
uh but he used terms like scalability
08:10
and use terms like life cycles and
08:12
orms and and backwards compatibility and
08:16
like especially on the backwards
08:17
compatibility i remember
08:19
uh back then being kind of like this
08:23
like yeah so i don't know about this
08:27
uh and and so basically i did what most
08:31
which is nothing i remained skeptical
08:34
and i was like i am not going to adopt
08:36
this thing so google io 2018 came about
08:40
and googled 2018 uh just absolutely
08:42
changed everything for me
08:44
because at google oil 2018 they
08:47
jet tech uh components are like you know
08:50
what is what is included in jetpack
08:52
components and it was really interesting
08:53
because you had stuff like architectural
08:55
components you had behavior
08:57
you had ui and foundation and and the
09:01
you could standardize android
09:03
development so if you use emojis on your
09:05
application for example
09:07
here's a way for you to do emojis if you
09:09
use fragments there's a way for you to
09:11
navigation super interesting because
09:13
like everyone sort of like does
09:14
navigation in a different way
09:16
paging and room for databases and it's
09:19
wow there's suddenly there's like one
09:22
doing things and i know that if android
09:25
jetpack is a new thing for you
09:26
and and it was a new thing for me as
09:30
i you kind of you want to start slowly
09:33
but you not only want to start slowly um
09:37
if you're not a jetpack fan uh i am
09:39
gonna turn you into a jetpack
09:42
fan uh so we're gonna be changing this
09:46
um let's start with the basics because i
09:49
think if you've been an android
09:51
even if you've been an android developer
09:53
for a week uh you will have seen
09:55
something like this
09:56
uh which is an application's life cycle
09:59
we'll look at how this is this is a look
10:02
of how life cycles actually work in
10:05
again you have seen this before um but
10:08
in my previous slide uh we talked about
10:12
sales instance so um let's uh just go
10:15
back to my previous slide
10:17
where we talked about save the saved
10:20
let's say you have an application and
10:24
your your application looks like this so
10:26
you have your saved instance
10:28
um but let's make it a bit more real
10:31
so instead of like saving game states
10:34
we'll make it a bit more real and
10:36
we'll turn that into a number generator
10:39
application because that's the kind of
10:40
thing you want to build right if you
10:42
want to go into the play store
10:43
this is where the money is you create a
10:47
application and also you know notice
10:49
that it generates a number between 1 and
10:52
um which you know these are all the
10:55
now we have this application we have the
11:00
and usually if i if i had a if i had a
11:03
regular audience i would say so what
11:05
happens when i turn my phone
11:08
uh and there's always going to be
11:10
someone clever in the audience who say
11:12
well when it's on your phone
11:13
that number uh changes and some people
11:18
uh removing cursor from the screen yeah
11:21
um so some people go oh
11:25
like the number changes and and the
11:27
reason the number changes
11:28
is uh this is expected okay because
11:32
every single time you change the phone
11:35
a configuration change so you get your
11:38
phone you've got your phone
11:39
on your hands you get your phone your
11:41
turn and that's a configuration change
11:43
so every single time this will generate
11:45
a new number for you that is between 1
11:48
so already the behavior here is slightly
11:52
different than one would expect because
11:54
one would expect okay so when i turn my
11:55
phone nothing changes i still get the
11:57
um but no uh configuration changes cause
12:01
to uh uh change that and obviously i
12:04
will say here like i'll leave a caveat
12:07
i could very easily just have done some
12:09
like shenanigans with my codes and says
12:11
i'm gonna save that states and then if
12:13
you turn your phone uh
12:15
like the the number doesn't change uh
12:17
but i will i will continue and say
12:19
that um what is uh what i've been using
12:23
and state and for the specific case of
12:26
savings and space the amount of data
12:28
should be kept small
12:29
because the system process needs to hold
12:31
on to the the provider data for as long
12:34
ever navigate back to the activity so
12:37
let's say you had an activity
12:38
and you had like a bunch of navigation
12:40
in there when the user returns
12:42
you still want to keep that same number
12:43
in there so all this is kind of like
12:46
uh inside uh the memory uh but there is
12:49
a recommendation this is a
12:51
recommendation by google
12:53
which says you can only store 50k
12:56
of data so you can you can absolutely go
12:59
over 50k of data um but that's not
13:03
recommended so if you
13:04
if you phone google and say hey uh i'm
13:07
storing 60k updates and my application's
13:09
crashing or like it's not keeping space
13:11
you're on your own i'm sorry uh because
13:14
our recommendation is 50k of data
13:16
now uh let's um let's look at a
13:18
different demo here because
13:20
hey uh like the number generators are
13:22
great like we all love number generators
13:24
but let's look at a real demo and the
13:26
reason i want to show you this real demo
13:28
is i want to show you why uh this stuff
13:32
is important so i'm gonna bring my
13:35
cursor back to my screen
13:37
and i'm gonna show some code that i've
13:39
wrote that i've written in here so
13:41
uh what we have in here is we have a
13:44
very very simple application it's got an
13:46
uh it's got a class this is a data class
13:50
and what it does is it goes into an
13:52
external api that's the pokemon api
13:55
and it gets some pokemon information
13:59
uh i've got my clients in here and what
14:01
i'm doing is like i'm actually
14:02
debugging uh everything okay so i want
14:04
to make sure that i can see
14:06
everything my application does and to
14:08
show you i'm not cheating uh i'm gonna
14:10
my phone in here which hopefully we can
14:13
get on the right light
14:14
and i am gonna relaunch this application
14:18
and i wanted to see what happens when i
14:20
relaunch so basically it just goes
14:22
into the internet it just goes into
14:26
and it downloads some data uh then it
14:30
it just pushes to my phone however
14:33
what happens here is you will notice
14:34
that when i turn my phone
14:36
that's a configuration change something
14:40
and yeah so it just keeps on making that
14:44
over and over again every single time
14:46
okay and the problem with making the
14:48
http requests over and over again every
14:50
single time is that you are actually
14:52
using real data in here
14:53
like you are asking your uh whoever
14:56
your your customers are whoever the
14:58
people like your users are
14:60
you are actually using real data in here
15:02
and and that's a problem
15:05
now let's go back so this is uh this is
15:08
what the problem is
15:08
now one change that we can make into
15:16
we can use something called life cycles
15:20
is a way for you to fetch some data so i
15:25
pokemon methods in here i can fetch some
15:28
and uh that data gets saved into
15:31
my applications memory but not into the
15:35
so i'm using a lifecycle class in here
15:38
i have a i add a function into my
15:41
application that uses live data so
15:43
uh whenever anything changes in my
15:46
application live data just gets
15:48
uh just gets an announcement here saying
15:50
hey uh just to let you know there's been
15:54
so we will pay attention specifically to
15:57
here and the the list that comes
16:00
inside our live data now i obviously
16:03
appreciate some people may not have used
16:05
live data before so let me just explain
16:08
what live data is very quickly for you
16:11
you have your ui in here so this is this
16:15
is the application example i just used
16:17
and then you have your live data object
16:21
the data for you so all the data that
16:24
on the screen is inside the live data
16:26
object so so you can think about like if
16:28
you wanted to make a
16:29
an analogy here you can say everything
16:32
that is on live data is like live data
16:33
is almost like my database okay so you
16:35
have some data that gets stored in there
16:37
and uh the ui is always observing live
16:42
is basically saying hey live data if
16:44
there's a change i want to know about it
16:45
i want to get an update so in this case
16:49
i have an api which is the pokey api
16:52
that i'm using and whenever there's a
16:56
live data will fetch those changes uh
17:00
gets updated and live data will then
17:02
tell my application that there's been a
17:05
uh my application would then react to
17:09
and do whatever needs to be done so in
17:10
this case you know some
17:12
some rogue pikachu just got into the
17:15
pokey api and just took over the whole
17:17
thing and everyone is a pikachu now
17:19
uh uh regardless of like uh which
17:22
and and that's how life data works so um
17:26
but now when you look at this
17:27
application here you're probably
17:28
thinking oh cool okay so um
17:31
what if i what if i wanted to be able to
17:34
on on that pikachu and uh
17:37
see some details for example like how
17:42
so that's where uh navigation components
17:45
come about so navigation components are
17:49
basically do what the name says you can
17:52
uh using navigation components so you
17:54
can click on one of the items
17:56
and you can navigate between screens now
17:58
the beauty of navigation is it basically
18:01
handles all the data going forwards and
18:04
coming back to you so um with
18:07
navigation you don't need to keep
18:08
control of that data
18:10
because the navigation components do
18:13
uh the way navigation components this is
18:16
uh this is what a regular navigation
18:20
um so in a simple application i you know
18:23
i i very much like the idea of like
18:24
using a standardized way like that's
18:27
and it can those navigation components
18:30
entire backstack for you so when a user
18:33
navigates back and forth for example
18:35
the application just keeps keeps track
18:38
um our pokemon application is a perfect
18:43
of something like this because
18:46
you could very easily just use the
18:48
navigation components
18:51
along with fragments to build something
18:55
a single activity application so instead
18:58
of having all the activities that you
19:00
have in here you have one activity a
19:02
single activity application
19:04
and you would use just like fragments to
19:07
things around now navigation is a huge
19:10
topic like there's a lot uh with
19:14
uh video i would suggest watching like
19:16
if you haven't done
19:17
anything to do with navigation or
19:19
specifically single activity
19:22
uh there's a good talk by ian lake on
19:24
this so this is one i had the pleasure
19:26
back in 2018 android dev summit it's on
19:30
and uh there's a link on my slides i
19:32
will be publishing those lives later as
19:34
well so you don't need to
19:35
uh be copying uh these links from here
19:39
now navigation also has something that
19:41
is uh uh in my opinion is like the
19:44
is the biggest selling point for me
19:47
uh what you can do with navigation and
19:50
i'll just i'll just kind of give you an
19:53
i i very often go into slack overflow
19:56
and i i look at like what are the
19:59
android developers asking
20:01
the most like what are the questions
20:02
android developers are asking the most
20:04
uh and and i like doing this because it
20:06
helps me with like creating my contents
20:08
like if i want to go and write something
20:10
for our blog for example
20:11
uh you know it's it's cool to write
20:13
about something new but it's also cool
20:14
to go and try and solve like answer
20:16
some people's uh questions so i do that
20:20
and one that kind of like uh um got my
20:24
looking at stack overflow if you look at
20:26
the tab i'm looking at the frequent
20:31
the question is how do i pass data
20:35
in an android application and i
20:38
went on and i clicked on this and i
20:40
noticed like it's got a lot of uploads
20:42
uh it's got a lot of like answers as
20:44
well uh there doesn't seem to be an
20:46
answer that is like the right
20:47
and so like i don't think there was one
20:50
uh but the most interesting thing here
20:54
there are a lot of pages
20:58
and there are a lot of ways to actually
20:60
skin a cat in here like you can you can
21:03
navigation in so many different ways and
21:06
like people do them in so many different
21:08
and i think this is the point of like
21:10
using navigation components okay because
21:13
and and again uh this whole like
21:15
scrolling was just one page
21:16
this is three pages of this okay so i
21:20
uh i can even run this thing back for
21:21
you uh in case you want to see that
21:24
uh it's quite it's quite pretty to look
21:27
but the point of like using navigation
21:31
it's one way of doing things and it's
21:32
one way that your entire team
21:34
will know how to do and that's something
21:38
um because in in a lot of these cases
21:41
and i looked at a lot of these answers
21:43
here in a lot of these cases there's no
21:45
or wrong like some people just implement
21:47
things in a different way but there's
21:49
not really oh yeah this is the perfect
21:50
way of doing that's definitely the way i
21:53
but there's no right or wrong uh and the
21:56
navigation specifically passing
21:58
arguments between uh
21:59
between navigation so this is a this is
22:02
a quote by lila uh fujiwara who works
22:06
and uh the way lila describes
22:09
navigation uh safeargs like passing safe
22:12
arguments in navigation it's navigation
22:13
components generates classes based off
22:15
your navigation graph
22:16
uh to ensure type save access to
22:18
arguments for destinations
22:20
and actions so this is really cool
22:23
everything that you pass between one uh
22:26
activity to the other using navigation
22:30
if you use safe fonts you're basically
22:32
saying yeah this is
22:33
all type safe which is great and
22:35
implementing this is very very easy
22:37
so in this case i have my i have my
22:40
navigation graphing here
22:41
i create on arguments which is the
22:43
arguments i want to pass
22:44
and i can even have a default value so
22:47
in this case i'm passing no and i'm
22:48
saying this is an argument type string
22:50
on the other sides if something tries
22:52
and reads anims for example that's
22:54
obviously not going to work
22:55
so it's making uh it's making it a type
22:58
which is which is super cool
23:02
then all my uh on my activity so this is
23:04
the button like if i had an on click
23:06
so when you revered your project uh you
23:10
uh directions class uh which you can get
23:13
or an instance of and then in this case
23:15
what i'm doing is i'm updating the name
23:18
and i can call navigate passing
23:20
information so again just
23:22
using a single activity application i
23:24
can just go and update the name of my
23:27
um and then obviously on the other side
23:31
like when my view gets created i just
23:34
now if you're um in your receiving so
23:37
that's your you're receiving
23:38
uh um destination now
23:42
here's uh how that would look like so i
23:44
have bubba soren here
23:46
and when i click when i click on
23:48
bulbasaur it turns that into cute boba
23:51
source so this is just like passing a
23:53
okay it's not changing anything in a
23:55
database it's not doing anything special
23:57
it's just passing on a string now
24:01
uh when we're when we're passing a
24:03
string with safehogs it's great like if
24:06
uh stuff to a database but we haven't
24:09
um what if we wanted to persist this
24:10
like what if i wanted to
24:12
really rename my boba sewer so
24:15
everywhere when i look on my screen
24:16
i see uh cute boba sword for example
24:19
like what could i do
24:20
if i wanted to do that uh so this is
24:24
um this is where room comes in so
24:26
there's a library for that too
24:27
and uh the way room works is room is a
24:30
persistence library that provides an
24:32
abstraction layer for sqlite so
24:34
if you've ever done anything with
24:37
um you will know what a pain it is like
24:39
you will know what a pain it is to
24:41
an application that uses sqlite just
24:45
natively i have used things in the past
24:48
uh like realm for example uh rome was
24:50
actually pretty cool
24:51
uh but i do think rome is is kind of in
24:55
is is the thing i've been using the most
24:58
gets the best of realm and it gets the
24:59
best of like just using sqlite
25:02
um and and in my opinion that's kind of
25:05
the way i always go with now um
25:08
if i again there are many many ways of
25:11
doing database interactions i'm sure
25:12
that if i go into stack overflow
25:14
there's like a few different ways of
25:18
um but the way you start using is we
25:21
a pokemon data class as i showed during
25:25
previously and it looks uh it looks
25:27
something like this i have my
25:28
name for a pokemon and i have a url um
25:32
what i then do is i create an entity so
25:36
uh on an entity and i give it a name so
25:39
i can i can call my table whatever so
25:41
i'm calling my table pokemon
25:43
um so i haven't really made any changes
25:46
and i'm setting up a primary key like
25:48
i'm giving it a primary key and i'm
25:50
saying my perma key it also generates so
25:52
whenever i add any pokemon
25:53
uh it just gets a new uh it just gets in
25:56
uh so not doing anything special in here
25:59
uh but we can also rename columns uh
26:02
in here like if we wanted to if we
26:03
wanted named to be something else or if
26:05
like pokemon name for example uh we
26:09
remember i'm getting all these data from
26:10
an api so i obviously don't get things
26:14
but if the api has some like cryptic
26:15
names for example i could just change
26:18
called something that is more useful to
26:22
then i create a data access object so
26:24
this is just an interface
26:26
and here is where i can go and just
26:29
all of the the things i want to do all
26:31
the actions i want to do so i have an
26:32
insert i have an update
26:34
i have a query where i just go and
26:36
select by name for example
26:38
and and the really really cool thing
26:40
about this like the really cool thing
26:42
with android studio is they are all
26:45
at compile time and and uh i find this
26:49
really interesting so
26:50
what i mean by text by compile time is
26:52
if i if i have a typo on my codes for
26:55
i'm going to get an error that looks
26:57
like this so cannot resolve symbol
26:59
um so it's all it's all checked in
27:03
which i find super interesting uh and
27:06
if i fix that then the error kind of uh
27:08
disappears so this is
27:09
like what android studio does for you
27:11
out of the box like you don't need to do
27:13
anything as long as you're using
27:14
the uh the room library this is what
27:18
android studio does out of the box
27:19
then the next thing i need to do is i
27:21
need to actually set up
27:23
my my database so i need to implement my
27:26
database so i'm saying where my entities
27:28
are obviously i can have multiple
27:30
i'm giving this a version so if i want
27:33
to go and bump the version i can just
27:35
and i set my pokemon's database and i
27:39
i'm using pokemon gao i could have
27:42
multiple gaos as well like you could
27:44
uh data subjects in here and then the
27:47
last thing i need to do is i just have a
27:49
repository i'm using repository in this
27:51
and i'm saying here's what my database
27:55
uh remember we named the table in the
27:57
past now we're naming
27:58
the database and i am just initializing
28:02
uh my uh pokemon database and i'm saying
28:05
room.database builder so just like
28:07
really initializing it and then i can
28:09
start doing my queries
28:15
let's uh yeah okay so
28:18
uh and this is this is my database
28:20
initialization initialization but i
28:22
uh i wanted to show you like what this
28:25
code as well so i'm gonna come out of my
28:29
and i'm going to show you some of my
28:31
codes i'm going to switch
28:38
and this is like the amount of changes
28:42
on this application okay so obviously
28:44
i've created my dao here
28:46
uh my dates access object i have a
28:48
methods for each one of the things so i
28:51
for insert i have a method for update
28:55
i have a delete and i have a select by
28:57
name uh i have a repository here
28:60
my repository is basically the thing
29:03
on on the on the slides uh i'm making
29:06
sure things are async and everything and
29:08
i have my database in here um so
29:12
this is not much different from what it
29:15
go and run this application
29:19
and when it finishes compiling hopefully
29:22
i'll be able to show you a little bit of
29:26
this is working right now
29:32
let me try and bring this here
29:36
so i have my bulbasaur and
29:39
what i can do is i can from the
29:43
i can do things like i want to make this
29:46
and then the bubba store becomes my pet
29:49
so now i can go back
29:50
i can go look at ivysaur for example i
29:52
saw is obviously not my parents
29:55
but if i go back to bulbasaur i can see
29:56
boba store is my pet
29:59
and the way i'm doing is the way i'm
30:01
doing this i'm just adding bulbasaur
30:03
into my database and i'm saying uh
30:06
i'm setting a boolean flag to say
30:08
bulbasaur is my pet
30:10
uh just very simple as that so i'm not
30:12
doing anything special here
30:14
um but it's kind of cool that i can um
30:17
that i can get database like going
30:19
on on my application without
30:22
actually having to write too much code
30:25
um like i usually do this i usually do
30:29
usually when i do this presentation i
30:32
uh this part because it's it's so simple
30:35
but like in the interest of time and
30:37
giving people some um giving people some
30:39
time for questions i just don't wanna
30:41
uh i just don't wanna take up all the
30:44
i'll go back into my slides here so we
30:47
looked at that demo
30:51
now if you wanna um if you wanna know
30:54
there are gonna be a couple more uh
30:58
today um so we obviously have uh camera
31:02
uh camera x is i'll say it's probably my
31:08
in in jetpack i i had a lot of fun
31:11
building things the camera x i wrote a
31:13
blog post about it so you can check it
31:16
and there's also become a composer so i
31:18
purposely didn't mention those things in
31:20
my application even though camera x is
31:22
probably my favorite library on jetpack
31:24
i didn't mention those things because i
31:25
knew uh brian and xavier
31:28
were gonna talk about those two things
31:29
so brian is talking about become a
31:32
uh divya is talking about camerax
31:35
super super interesting uh it's still a
31:38
fiddly as you will see today uh but it's
31:40
super super interesting and i think uh
31:42
brian would do a good job at explaining
31:44
um with that uh like i said i will be uh
31:48
posting those lines later
31:49
i'll put it on whatever hashtag uh greg
31:53
uh on twitter uh you can find me on
31:55
twitter on marcus blacone on twitter
31:57
uh all this code is on github it's going
32:00
to be on my github account
32:02
and uh you can check a lot of my sorts
32:05
answers to stock overflow questions uh
32:09
answers or even like a lot of the the
32:11
open source stuff that i write so you
32:12
can find it on paco.cod.jk which is
32:15
my website with that i want to thank you
32:19
and i want to thank drugcon very much
32:21
for having me i have been marcus
32:23
blackcon it's a pleasure to be here
32:25
marcos thanks so much fantastic
32:27
presentation really appreciate you being
32:30
we have uh q a i'm going to have uli
32:32
change himself to the presenter so
32:35
the top questions that were voted on
32:37
we'll give you 10 minutes to answer them
32:39
uh and i'll i'll bring everyone back in
32:42
uh and introduce tivia after that
32:46
cool so feel free to fire away marcus
32:52
cool uh all right so i'm looking
32:55
at the first question with multi-modular
32:59
working each module at least one
33:03
on the rise is on a single
33:08
i'm not sure i really understand uh
33:12
the question here with multi-modular
33:15
architecture where each module equals
33:17
okay so where each module
33:19
equals at least one activity
33:22
on the rise is the single activity i'm
33:26
updated i'm not sure i understand this
33:31
uh if there's anyone else who wants to
33:34
help me answer the question because i'm
33:35
not sure i even understand it
33:38
i'm gonna move on to the next question
33:39
and come back to this uh so
33:41
the next question is is there any
33:43
performance difference between
33:44
is there any performance differences
33:46
between implementing an app
33:48
with multiple activities and
33:49
implementing an app with one activity in
33:53
uh i haven't seen anything like this uh
33:56
using multiple fragments uh
33:58
in my in my my opinion as a as a
34:01
developer using multiple
34:02
uh fragments this complicates your code
34:06
a little bit um but i haven't seen
34:09
uh any kind of like performance
34:11
differences what i would say is if your
34:13
application is very complex you probably
34:15
don't want to make it
34:16
a single activity application and just
34:18
keep on like spawning uh new fragments
34:21
but if you're if you have like an
34:23
application like the pokemon
34:25
uh application for example that i just
34:26
showed you uh that is the perfect
34:28
contender for like just using most
34:30
fragments because you don't have many of
34:32
them i'll say if you have
34:34
many fragments then you just need to be
34:40
next question in and the questions keep
34:42
on like popping around which is really
34:45
uh in a multi-module project what's the
34:49
using navigation jetpack to go from
34:54
in module a to fragment in module b
35:02
module project what's the best design
35:03
using navigation.pack
35:11
i'm not sure i get this i know this is i
35:13
know we're talking about multi module
35:15
but i'm not sure i get the question
35:20
i don't i don't think you do anything
35:22
different in here like i i
35:24
work with some applications that are
35:26
mostly module and i've been using
35:28
fragments on those applications so i
35:30
don't think you do anything different in
35:31
here other than just like
35:33
injecting the the fragment um
35:37
i don't think there's anything different
35:40
that you need to do
35:43
unless i didn't quite get the question
35:50
this one already uh
35:54
now the next question i'm going to go to
35:56
if i'm using the same fragment in
35:58
different navigation
35:60
graphs i need to update
36:03
the question just disappears
36:10
what is the best way to map nessa jason
36:12
into a room database
36:14
uh okay i'm gonna answer that because i
36:18
i'm gonna answer that because it's the
36:19
one i got to read what is the way to map
36:23
what you do is i usually just try and
36:26
into a data class i get a i get my data
36:30
map it that way uh so json entities
36:34
into you you have a lot of like
36:38
i've used a like what i did last time i
36:41
i've used the generator that basically
36:43
takes my json turns into like a
36:45
uh uh pojo and i just
36:48
pasted that into um into android studio
36:52
under studio obviously just um
36:56
that oh there's someone saying script
36:59
um android studio always translated that
37:02
to kotlin and then i just turned that
37:03
into a data class and that's the easiest
37:06
uh like it does i'd say it does like 90
37:12
yeah that's that's how i do it uh do you
37:15
think it's the best practice to use
37:17
activity per feature jesus
37:20
i'll move to the browser okay because
37:22
i'm looking at the i'm looking at the
37:23
screen here but it keeps on popping so
37:25
i'll move to the browser here
37:39
hang on i'm just opening here
37:48
is there a reason you prefer using
37:49
navigation save fogs instead of
37:52
a parcelized data class in kotlin
37:55
plus the new intent fragment.new
38:02
to that so so i'm going to read the
38:03
question again is there a reason to
38:05
using navigation say fogs instead of uh
38:08
personalized data class
38:09
in kotlin plus the new intent
38:12
fragment new instance pattern uh i'll
38:14
say no i i think that's more of a
38:17
if i'm using if i'm using jetpack which
38:20
is what i tend to use right now
38:22
uh whenever i use it i just use safehogs
38:24
i don't think there's a right or wrong
38:26
in here unless i didn't get the question
38:28
right but i don't think that's all right
38:30
uh using using sorts of like new intent
38:33
uh with fragment.new instance pattern is
38:36
you're kind of like going it's almost
38:37
like you're going under the hood on the
38:39
on the navigation safehart so
38:41
i i'll say this is probably more of a
38:43
preference thing than anything else
38:47
all right marcus we have time for we
38:49
have time for one more question
38:51
uh so let's possibly two uh but let's
38:54
try to get two more questions and then
38:57
okay uh moving on to the next one and
38:60
i'm looking at my browser now because
39:01
uh like just looking at the screen here
39:04
just keep on changing uh what about data
39:09
uh is it parts of jetpack if used
39:12
uh with any tool doesn't it result
39:16
in untestable codes uh data binding
39:18
doesn't uh it doesn't result in
39:21
no um data binding is
39:25
you can use it as parts of jetpack yes
39:28
i use data binding a lot um i'm not sure
39:32
it results in accessible calls i think
39:36
i you know i think most of the
39:39
accessible codes i've seen
39:40
is like written by developers and
39:42
suppose just using functionality
39:44
uh so i would say uh i don't think it
39:46
results in untestable goals unless
39:48
you you had like a different experience
39:50
like i never really had an experience
39:53
i've used data binding and i used data
39:54
binding a lot and i never really had an
39:56
where uh like i can test all my code
40:07
yes there is one question here that says
40:10
uh aren't async tasks uh deprecated yes
40:14
async task is deprecated as i was
40:15
talking about it today like looking at
40:17
my codes i was like
40:18
yeah i should have changed that yes
40:20
async tasks are deprecated you should
40:22
you should move away from using async
40:26
the there are definitely
40:29
uh new different things that you can use
40:31
i actually wrote an entire blog post
40:33
uh so if you want to know uh what you
40:37
what you can use instead i wrote a blog
40:39
post on thecurla.com.jk where i talk
40:42
uh async tasks and and their deprecation
40:46
mr anonymous uh async tasks are
40:51
marcus thanks so much thanks also for
40:53
playing question roulette with us
40:58
you know uh so we'll well this is a
41:00
process we're going to refine in the
41:02
next but uh hopefully we'll be cycling
41:05
always the top three voted on questions
41:07
will appear on the screen
41:09
the latest question will keep appearing
41:11
down below and changing
41:12
uh so hopefully uh that'll smooth out
41:15
but thanks for playing roulette with us
41:17
on the questions and for the fantastic
41:21
no worries my pleasure thank you
41:23
everyone for having me here again
41:24
uh i'm happy to answer your if you have
41:27
a question i'm happy to answer those
41:29
on twitter as well so just like uh at me
41:31
on twitter and i'm happy to try and
41:33
answer your questions here thank you
41:35
thanks so much i'm going to switch over
41:53
okay um hi everyone i'm hoping you guys
41:59
and perfect okay um
42:03
hi everyone i'm divya i am
42:06
a mobile developer with a ticket selling
42:09
uh company called game time in san
42:13
and i have been doing um android
42:17
five almost five years now um
42:20
before i start i want to really give a
42:22
huge shout out to the organizers of
42:24
droidcon and everybody who's here
42:26
uh thanks for coming and like listening
42:30
listening to us um so today what i'm
42:33
gonna quickly talk about
42:35
is the camera x library and thanks to
42:38
uh for alluding that it's his favorite
42:42
but um so it's my favorite too i
42:45
uh i have been using it in a lot of apps
42:49
uh let's get started
42:52
so in um today's world there are as we
42:55
all know there are a wide variety of
42:57
apps that needs camera
42:59
support for different sorts of
43:00
functionalities a few cases can be the
43:04
photo previews and capturing social
43:07
messaging instagram etc all kinds of
43:10
image processing which is an entirely
43:12
new world in itself
43:14
like scanning barcodes documents again
43:17
photos of any sorts
43:19
filters special effects and so many more
43:22
and as marcos alluded in the beginning
43:25
um the pre 2017 or 2018
43:30
uh for that matter um incorporating
43:33
camera into your app was definitely an
43:36
anxious task now the camera to api which
43:39
is part of the android hardware
43:40
package is like was powerful but it can
43:43
be tricky to get the most out of it
43:45
different and wide ranges of devices
43:48
have their own specific camera
43:49
capabilities that they offer
43:52
which means lots of device specific code
43:54
just to have a vast
43:56
device support focusing on nitty
43:58
gritties of tons of boilerplate code
44:01
difference in configurations based on
44:04
orientation rotation preview size
44:08
so to overcome all these problems we
44:14
now what is camera x and y so it
44:18
uh as part of the jetpack library
44:20
behavioral component
44:21
camera x library allows integrating
44:24
camera functionality
44:25
into your android app with just a few
44:29
and easy to use api surface now
44:32
internally it still level
44:34
leverages the capabilities of camera 2
44:36
which is the interface to the native
44:39
but all you need to care about as a
44:40
developer is the use case or the actual
44:45
instead of worrying about consistencies
44:47
across different devices and lots of
44:49
code now it not only gives you backward
44:52
compatibility support but
44:53
also uses a much simpler use case based
44:57
which means all you do is focus on the
45:01
and the library takes care of internally
45:03
accommodating that use case
45:05
on the supported devices without you
45:07
having to write any such specific code
45:10
it is also more focused on enabling you
45:13
integrate new capabilities and apis to
45:17
camera features in your app also camera
45:20
x has been highly optimized for its
45:22
performance and size
45:24
thus making integration of camera in
45:26
your app seamless and not frustrating at
45:29
so this camera x library allows you to
45:32
bind to the life cycle of the owner
45:34
which means no manual intervention
45:36
needed for managing the life cycle
45:39
and also as part of the optional add-on
45:42
we do get the supported effects like hdr
45:49
so the several basic use cases that can
45:52
be easily configured
45:54
currently with camera x are a the
45:57
which as the word itself means lets you
46:01
on display before it's captured
46:05
along with capabilities like rotate crop
46:08
so all that you need to do is code wise
46:11
is add a preview view which is nothing
46:13
but an extended view on which
46:15
it is rendered the second one is image
46:19
which is a use case that actually gives
46:21
you a cpu accessible image
46:24
which can be passed on to different
46:25
analysis algorithms like machine
46:28
facial recognition or any sort of image
46:31
through something called the analyze
46:32
method and i'll get into the
46:34
coding aspects of all these use cases in
46:37
the third is the image capture which is
46:40
the most obvious use case of capturing
46:42
high quality images with functionalities
46:44
autofocus auto exposure and other basic
46:48
it also gives you the option to choose
46:51
to provide an in-memory buffer of the
46:52
image or save the image to a file
46:55
through the take picture method so also
46:58
note that these use cases can be
47:01
combined with one another
47:02
and can be run together in one floor for
47:05
example the basic functionality
47:06
of a camera that entails previewing the
47:09
image through the image preview
47:10
and then actually using the image
47:12
capture use case to
47:13
click the photo and save it to the
47:16
now the one recommendation when
47:18
combining use cases is that concurrent
47:20
use cases should be bound
47:22
to the same life cycle which ensures
47:24
that the camera resources are
47:26
active when necessary and released in an
47:28
efficient manner when not needed anymore
47:31
and again you don't have to worry about
47:33
any memory lake or anything
47:38
so now in order to get started with
47:41
and demonstrate how you need to write a
47:44
minimal amount of code in order to carry
47:46
out the actual task
47:48
you basically just need to specify three
47:51
configuring the actual use case with its
47:53
own set and build methods
47:55
b attaching listeners to specify what to
47:58
do with the output data
47:59
and also binding to the owner's life
48:02
cycle as i mentioned
48:03
which means again we don't have to worry
48:05
about specifying start or stop methods
48:08
but it becomes the responsibility of the
48:10
life cycle owner to update camera x to
48:13
its state changes matching the life
48:18
so for example uh to specify the basic
48:21
use case of image capture
48:23
we only literally need this much code to
48:26
have an image capture pipeline
48:28
basically use the image capture builder
48:30
method to specify the use case
48:31
and then we can provide additional
48:33
configurations like target resolution or
48:36
but the best thing is even if we don't
48:38
the api falls back to the nearest
48:40
supported resolution
48:42
on the device it's running which makes
48:44
this widely supported on a variety of
48:48
then we bind it to the owner's life
48:50
cycle by using the bind to lifecycle
48:52
which gives us the flexibility not to
48:54
worry about the state machines
48:56
camera itself opens when needed and
48:58
released when not needed
49:00
and then finally use this use case
49:04
which here becomes the take picture
49:07
also has a listener attached to it which
49:09
is the on image save listener
49:11
which lets us handle the saved image in
49:14
also specify the error handling
49:20
now again before we get into the actual
49:22
coding details of each use case and
49:23
other specificities
49:25
let's start with some basic janitorial
49:27
details about how to get started with
49:29
using camera x library in your android
49:32
now the library is currently in beta
49:35
which means it is almost production
49:38
possibly with bugs but i it's
49:41
continuously being worked on
49:43
so uh in order to integrate it into your
49:46
app we need minimum api level
49:48
to be 21 or higher and also since
49:51
we are binding to the lifecycle methods
49:53
we need the android architecture
49:59
it is also recommended to use uh
50:01
fragment activity or
50:02
app compact activity since they are by
50:04
default lifecycle aware
50:06
activities also we need to add basic
50:09
dependencies to our
50:11
gradle file like the google maven
50:13
repository compile options
50:15
and the actual camera x dependencies
50:18
now since we are using the camera
50:20
utility in our app it is needless to say
50:23
needs the camera permission and so
50:26
use cases are launched we just need to
50:28
ensure that the app
50:29
requests for the camera permission if it
50:32
and also any other necessary permission
50:34
like the right external storage
50:36
for saving the captured photos
50:41
so as i specified before the preview use
50:44
is all about viewing the preview of the
50:49
captures and we need to set the preview
50:52
first by configuring the preview builder
50:55
and then building it so hence the build
50:58
now the set target resolution or the set
51:01
target rotation here that you see are
51:03
some of the configuration methods that
51:06
that lets you make your use case a lot
51:09
based on what you want to do on a
51:11
necessary supported device
51:13
now apart from building the use case
51:15
preview also needs an
51:17
actual surface to render the frames uh
51:20
received by the camera
51:21
now in order to automatically handle
51:25
or translating the preview frames to
51:29
the library comes with something called
51:30
the preview view which is
51:32
nothing but a custom view that can
51:34
easily be attached to a preview
51:36
use case so hence we use the method
51:39
view create service provider
51:43
to create a surface provider that you
51:44
can then pass to the preview use case to
51:47
start the preview stream
51:49
and finally this review use case is
51:51
passed to the camera provider when it's
51:53
bound to the owner's life cycle
51:55
as indicated by the code here
51:60
talking about the next use case of
52:02
analyzing the images through camera x
52:04
this one allows you to run any sort of
52:06
analysis algorithms or machine learning
52:08
over the camera images
52:10
so similar to the preview use case we
52:12
use the image analysis builder to
52:14
configure the use case
52:15
and then build it using the build method
52:18
application here implements the analyze
52:21
which is run on frames that are received
52:26
but here there are additional
52:28
configurations involved like the set
52:30
back pressure strategy which basically
52:32
determines how the images for the
52:34
analysis are selected
52:38
so now this back pressure strategy
52:40
itself comes with two modes
52:42
which is blocking and non-blocking the
52:45
is strategy block producer which means
52:48
the new frames that are blocked from
52:50
entering the pipeline of the executor
52:52
are they're blocked
52:53
until the method returns so the frames
52:55
that are received by the executor
52:59
so if the analyze method which actually
53:01
carries out the analysis or the
53:03
takes longer than the current frame rate
53:05
the analysis may not be updated
53:07
on the latest on the latest frames
53:12
on the other hand we have the
53:14
non-blocking one which is the strategy
53:17
in which the analyze method always gets
53:20
the latest availability from the camera
53:22
so in case of a latency there might be
53:26
which might be skipped only when the
53:28
frame being analyzed is closed by
53:30
calling the image.close method
53:32
the next latest frame is received and
53:34
entered for analysis
53:38
now the third use case which is the
53:39
image capture use case is for capturing
53:42
high quality and resolution photos
53:44
which automatically provides the
53:45
functionality of basic camera controls
53:48
and other utilities like
53:49
exposure focus etc now as with the other
53:53
again we first configure the image
53:55
capture use case with image capture
53:57
and then build it with the build method
53:60
now here we also have the option to
54:02
decide how to use the captured image
54:04
with the help of the
54:05
image capture take picture method which
54:08
has the option of either providing the
54:10
in-memory buffer of the captured image
54:12
or provide a storage file location to
54:16
we can also customize the executors on
54:19
which the image capture runs
54:21
so it can be a callback executed in
54:23
which we can provide our own
54:25
on image captured callback or it can be
54:28
input output executor which can also
54:31
assist with saving the image to a file
54:35
so camera x is flexible enough to
54:37
default to an internal input output
54:40
in case the executor is present now also
54:43
we can configure it
54:45
the we can also configure the captured
54:49
optimized either for latency or quality
54:54
capture mode configuration such as
54:57
minimize latency or capture mode
55:04
apart from the use cases camera x also
55:06
gives you high level apis to control the
55:10
and the camera automatically reflects
55:12
the updated state for all of its use
55:15
for example camera x by default supports
55:19
but there might be a use case where we
55:21
might need the flexibility to control
55:23
the focus target manually
55:25
now with the traditional camera to api
55:28
this needs a lot more calculations with
55:30
figuring out the transformations between
55:32
the ui coordinates and the camera sensor
55:34
coordinates and then calculating the
55:37
but with camera x library it already
55:40
comes with these advanced methods
55:41
or apis like surface view metering point
55:45
or focus metering action which
55:47
automatically does these calculations
55:49
and you pass them to the camera control
55:51
and it handles all these things
55:55
similarly for something like supporting
55:58
camera to api required us to manually
56:02
figure out the transformation and crop
56:03
region but with camera x library
56:06
there is something called a scale
56:08
gesture detector which determines the
56:10
delta value or the scale factor
56:12
with the user pitch value and we can use
56:16
automatically figure out the crop region
56:18
and send a request to camera
56:20
so your pinch to zoom is implemented in
56:23
just a few lines of code
56:25
another example is the linear zoom
56:29
uh again camera x comes with its own set
56:32
linear zoom method which just takes a
56:36
and does the necessary zoom
56:37
transformations on its own
56:39
so which means that you can implement
56:41
something like zener
56:42
linear zoom slider in just to one line
56:46
and the best part is that camera x
56:48
follows the principles of automatic
56:51
which means that it automatically
56:53
provides functionality that is specific
56:56
and that your app is running on so on
56:59
if you didn't provide an attribute or a
57:02
or an unsupported configuration it will
57:05
gracefully fall back on the nearest best
57:09
so again we as developers don't have to
57:11
worry about device specific code at all
57:16
so as mentioned before camera x also
57:20
into external effects like hdr
57:23
night mode that are available on
57:25
specific devices with your camera
57:27
so in your app you can query if an
57:29
extension is available
57:31
the extension should be supported and be
57:33
physically present on the device
57:35
and if it is available and supported it
57:39
else it will again degrade gracefully
57:41
and default is always the camera x
57:44
so basically to apply any of these
57:47
all that you need to do is create an
57:51
uh as shown here in the code it lets you
57:53
configure the builder
57:55
with the extension setting and then
57:57
query for the availability of the
57:59
and enable it if it's there
58:03
um here i have just a very basic small
58:07
uh video of a demonstration which is
58:10
the preview functionality and then
58:13
actually capturing the
58:14
uh the capture use case and uh the
58:18
android uh the github repo repo for the
58:23
a lot of code there which you guys can
58:25
go and check out and
58:27
it basically covers all the use cases
58:30
a live like it gives you a lot of
58:34
which makes writing uh
58:37
which avoids writing uh any of the
58:40
and also the official um the
58:44
developer and developer.android.com
58:47
is the best site i i felt for learning
58:50
camera x library so i know it was a very
58:54
quick uh lightning talk but i'm happy to
58:58
um answer any questions you can find me
59:01
on twitter anytime and
59:03
dm me um and i'll be happy to answer
59:05
your questions right now but thank you
59:12
give me a thanks so much thanks so much
59:14
i always always after these
59:16
presentations i always hate that we
59:17
don't hear all the applause and i feel
59:18
like i need to applause for everybody
59:20
but thank you so much uh are you ready
59:22
to play question roulette because that's
59:25
what you saw with marcos i'll tell you
59:27
but we think we've got that ironed out
59:28
so i'm going to make uh uli
59:30
right now our presenter and he should be
59:34
with the questions that are the most
59:36
popular so here we go
59:38
okay let's do it so the first question
59:41
is does camera x also include
59:43
qr barcode scanner um i am
59:46
not 100 sure if it actually comes in
59:50
like in it comes with a qr or a barcode
59:53
scanner but i know that the image
59:56
um use case would be the one that would
01:00:00
for this because you can basically
01:00:03
run a barcode run an own
01:00:06
qr barcode scanning algorithm in the
01:00:09
inside the analyze method
01:00:11
and then whatever image is being passed
01:00:16
uh scanned for barcodes or qr codes
01:00:21
okay um the next one is can the image
01:00:25
capture work be done
01:00:26
in a view model and does it need to be
01:00:33
image capture work be done in a
01:00:37
i believe that uh the
01:00:40
i as far as i know i think i believe
01:00:44
actual use cases camera x library
01:00:47
in itself takes care of the you know
01:00:51
the basic android principle of not
01:00:52
blocking the main thread so i believe
01:00:55
internally takes care of um
01:00:58
making sure that uh it is done on in a
01:01:02
it is done in an asynchronous manner and
01:01:04
not blocking the ui thread
01:01:06
but i can dig a lot more into this
01:01:10
i'll have all the answers the
01:01:13
uh even if i'm missing out something
01:01:16
twitter for you guys
01:01:19
does camerax address the 90 degree
01:01:22
rotation issues on some devices
01:01:26
i am not sure about this one but i will
01:01:29
again look into this one for sure and
01:01:32
get back to you guys how is support for
01:01:36
newer phones with multiple lens
01:01:41
i believe okay i believe that i have as
01:01:44
far as i've used it with my
01:01:46
android latest phone i have not had um
01:01:50
i've not had any issues but again not to
01:01:53
forget that the library is
01:01:55
in beta mode and it is continuously
01:01:58
worked on does it
01:02:01
have any ai or any type of image
01:02:05
or context recognition
01:02:08
so again i think going back to the same
01:02:11
as what i would say
01:02:12
to the same qr barcode scanning the
01:02:14
image analysis use case in
01:02:16
itself is pretty strong enough to
01:02:19
carry out any sort of uh image
01:02:22
processing or facial recognition
01:02:24
or any sort of other image analysis that
01:02:27
we are trying to do
01:02:28
and i would i would highly encourage
01:02:31
everyone who's trying out this library
01:02:33
to use the analyze
01:02:34
method in itself and see how
01:02:41
architecture component dependency is
01:02:45
recommended i believe it is required
01:02:48
again we are trying to ensure that uh
01:02:53
like we are trying to ensure that uh you
01:02:56
to a lifestyle to the life cycle of the
01:02:59
and so you as a developer will be will
01:03:03
um causing any issues with uh manually
01:03:06
starting the camera or
01:03:08
uh closing it and leading to any sort of
01:03:11
leading to any sort of like memory uh
01:03:13
memory leaks or any other errors
01:03:17
do we need to import all the camera x
01:03:19
dependencies or can we import
01:03:21
only the ones we need so the camera x
01:03:25
i think camera x core and the view are
01:03:28
that would be necessary but i believe
01:03:31
that the other ones
01:03:32
uh can be imported on demand
01:03:36
i will share the github repo and the
01:03:44
and okay the last one and as of alpha
01:03:47
release the take picture method does not
01:03:49
read the correct
01:03:51
information you will need to import the
01:03:56
i believe this uh i am i am
01:03:59
99 sure this uh issue would have been
01:04:02
resolved with the beta release so again
01:04:03
i would encourage everyone to try out
01:04:05
the latest beta release and see if the
01:04:07
issues are resolved
01:04:09
um yep i think we don't have any more
01:04:13
no we you got through the complete cycle
01:04:16
thanks for playing question roulette
01:04:18
appreciate it divya thank you so much
01:04:19
for being here and um
01:04:21
we'll have to have you back uh love your
01:04:23
presentation we're gonna have to have
01:04:24
you back for full length one to really
01:04:26
dive into some of the details so
01:04:28
get ready because we'll come knocking
01:04:29
for that later on
01:04:31
thanks everyone you have a great day
01:04:35
now turn the time over to brian gardner
01:04:37
and become a composer so i'm going to
01:04:39
to change over to him uh and make him
01:04:42
our current uh moderator and presenter
01:04:45
and uh here we go brian you should be we
01:04:48
should be seeing you as well now
01:04:51
there we go turn the time over to you
01:04:60
hello everyone uh my name is brian
01:05:03
am a developer and instructor at big
01:05:06
and today i get to talk about jetpack
01:05:10
so as marcos was mentioning uh compose
01:05:14
still pretty uh rough
01:05:17
around the edges let's call it um it is
01:05:20
dev release currently so pre-alpha even
01:05:24
so things are changing quite a bit uh
01:05:28
i like it it's a really fun way to build
01:05:31
user interfaces for android
01:05:33
so the goal for this talk i suppose i
01:05:38
is i'm basically going to try to
01:05:41
the list view from gmail
01:05:45
so there will be an individual list
01:05:48
item for each email i'll try to add a
01:05:51
toolbar at the top
01:05:52
floating action button as well as the
01:05:55
navigation drawer on the side
01:05:57
so i think compose is one of those
01:05:59
things that it really
01:06:00
is a lot better to kind of see it worked
01:06:03
or see an example worked through
01:06:05
so let's do that
01:06:09
so i have a little screenshot of
01:06:12
the main screen that i'm trying to build
01:06:16
and i have my studio open um so
01:06:19
the first thing that you're going to
01:06:21
need is you're going to need a specific
01:06:23
version of android studio uh so android
01:06:28
is the one you're going to want uh this
01:06:29
is currently in canary
01:06:31
but it's the only version that has the
01:06:33
actual compose tooling
01:06:35
the 4.0 beta doesn't have it 3.6 doesn't
01:06:38
so make sure you get studio 4.1
01:06:42
the next thing you're going to need is
01:06:43
some various dependencies
01:06:45
so inside of your android block
01:06:50
you can add these compose options this
01:06:53
a kotlin compiler version that you're
01:06:55
going to need in order to
01:06:57
get compose working you run into some
01:06:59
weird issues if you don't have this
01:07:01
compiler version specified
01:07:02
uh so you want that and then there's a
01:07:05
kotlin compiler extension version as
01:07:08
uh which you can see this is where the
01:07:10
dev release comes in
01:07:13
uh what you'll also need is the
01:07:16
actual dependencies themselves uh so
01:07:18
there are sort of two
01:07:20
versions uh that you'll need one is the
01:07:23
compose compiler and runtime
01:07:26
uh so this just makes sure that compose
01:07:28
can build and actually run
01:07:30
uh when you're using it and the second
01:07:34
uh libraries so this actually includes
01:07:37
like the text the buttons stuff like
01:07:41
so that's mostly what you'll be using
01:07:43
when you're actually building out your
01:07:45
whereas the compiler and runtime just
01:07:47
make sure everything actually works
01:07:51
um so in the interest of time this will
01:07:53
be a little bit like a cooking show
01:07:55
it's a little bit of stuff made fresh
01:07:57
and a good bit of stuff i've prepared
01:08:00
so one of the things i've prepared
01:08:02
earlier is a data class that represents
01:08:07
so i have things like the sender text if
01:08:10
is important which shows this little
01:08:14
the receipt time subject text body text
01:08:17
stuff like that so that just prevents me
01:08:19
from having to build that out
01:08:22
most of my time is going to be spent
01:08:24
building the actual
01:08:26
email view itself so the the individual
01:08:30
is what i'm mostly going to be focusing
01:08:33
so with compose there's no xml
01:08:36
thankfully um everything is going to be
01:08:39
built inside of kotlin
01:08:40
so when you want to create something
01:08:43
that shows on the screen
01:08:44
you need to create a function that's
01:08:46
annotated with the at composable
01:08:49
this tells compose hey this thing is
01:08:53
that needs to get displayed on the
01:08:56
so in this case i just have a top level
01:08:58
email view which will take in my email
01:09:00
and as i go through i'll actually build
01:09:05
now with compose i really like to start
01:09:08
up you start at your kind of most basic
01:09:11
view components and build your way up
01:09:13
uh so i'll start there so starting at
01:09:16
the top uh we could start with the
01:09:18
sender text right here um
01:09:21
so when you want to display text in
01:09:25
there's a text function so you just say
01:09:29
i have some text and i can set the text
01:09:35
that will actually render whatever text
01:09:39
in um now if i want to actually see this
01:09:42
working there's a couple ways i can do
01:09:45
one i could add this into my activity
01:09:48
throw my sender in there run it display
01:09:51
it in an emulator
01:09:52
but that's a little bit slow but what
01:09:55
you can do instead
01:09:56
is there is a preview option so
01:09:60
you can create a preview function
01:10:03
annotated with app preview
01:10:04
and at composable and this will render
01:10:08
this nice little preview pane over here
01:10:10
on the right hand side of studio
01:10:13
so right now i'm just rendering my email
01:10:15
view with a bogus email
01:10:17
but there's nothing in my email view so
01:10:19
nothing is rendering but if i did want
01:10:21
to render something
01:10:23
i could just say hey render my sender
01:10:27
you do have to build every time to get
01:10:29
the preview to actually work
01:10:32
hopefully this shouldn't take too long
01:10:34
as i was working on this a little bit
01:10:37
but there you go so you can say hey my
01:10:39
email view preview
01:10:41
is getting rendered and i have some text
01:10:43
getting displayed
01:10:45
that's great uh but say what if i wanted
01:10:49
this text what if the default style
01:10:53
well the good thing is the api for
01:10:56
is very fluent so it's
01:10:60
has a lot of nicety so it's like hey i
01:11:03
i can provide a text style the text
01:11:07
class has pretty much everything you
01:11:09
would need to modify
01:11:10
your text color font size letter spacing
01:11:14
text decoration like i said there's a
01:11:17
i'm not going to go through everything
01:11:18
here i'm just going to maybe tweak the
01:11:23
and maybe the font size uh maybe say
01:11:29
so color here is a specific object
01:11:33
you can pass in a hex value if you want
01:11:36
configure that appropriately or you can
01:11:38
just use one of these
01:11:40
uh defaults and in my case most of the
01:11:42
defaults are going to work
01:11:44
so i just use that the sizing here is
01:11:48
uh actually pretty nice so they provided
01:11:52
extension function on i think doubles
01:11:55
and maybe number uh but this basically
01:11:59
will convert this to the style and
01:12:01
or the scale independent pixels so it'll
01:12:05
both the density of the screen and the
01:12:07
user's accessibility settings
01:12:10
now if i refresh this the
01:12:14
preview isn't actually going to change
01:12:17
the color is the same and the text size
01:12:19
it's getting scaled anyways
01:12:21
so you're not really going to see much
01:12:23
difference but i messed with this before
01:12:25
and 20 pixels seemed all right
01:12:28
so what i can do next is i need to
01:12:30
provide my important icon
01:12:33
so this one i already added a
01:12:36
vector asset for this uh so to display
01:12:40
any kind of resource you're going to
01:12:42
want to use the icon
01:12:43
function you just provide an asset and
01:12:46
there's a vector resource
01:12:48
function you can use to load a vector
01:12:52
so this is my important icon
01:12:57
go back to code so this will just load
01:12:59
this asset and put it in
01:13:01
something that can load an icon so what
01:13:05
is the sender text and the icon need to
01:13:08
be displayed next to each other
01:13:10
along with the receipt time way over
01:13:13
here on the right
01:13:15
so what i can do is i need to create
01:13:19
composable function to basically contain
01:13:22
i could put everything in my email view
01:13:24
but that might make things a little
01:13:27
so i can create another composable
01:13:30
maybe call it email header
01:13:36
pass in the string and then this is
01:13:38
where i'll actually configure the
01:13:41
sender text and the receipt time
01:13:45
now everything needs to be displayed in
01:13:47
a row here and fortunately
01:13:49
there's a function called row so i can
01:13:53
i just want my sender with my sender
01:13:58
and in front of that i need my important
01:14:01
icon uh so i can then update this
01:14:06
to be my email header um
01:14:09
email sender and then if i
01:14:13
refresh the preview it should show the
01:14:17
important button in front of
01:14:20
my text which it does there's a couple
01:14:23
things wrong here number one the colors
01:14:26
number two the icon is actually a little
01:14:29
bit above the text
01:14:30
um so i can modify the
01:14:34
color of an icon so there's a tint
01:14:37
property which is really nice um i could
01:14:40
try yellow for this it doesn't quite
01:14:42
look right so i did some experimenting
01:14:45
and just grabbed the color for the
01:14:48
i think it's fffdd663
01:14:52
that should tint the icon so i'll just
01:14:55
go ahead and run that
01:14:58
and then my email header i need
01:14:60
everything to kind of be aligned
01:15:02
in the row so there's a vertical gravity
01:15:05
property that you can provide
01:15:08
and say hey please center all of the
01:15:11
contents vertically for me
01:15:14
so that should kind of move everything a
01:15:16
little bit the icon will move down just
01:15:19
to be in line with the sender text
01:15:24
so the next thing i need is the receipt
01:15:26
time uh there's nothing super
01:15:28
about the receipt time so i went ahead
01:15:29
and implemented this already
01:15:31
uh this just takes in the time that i
01:15:33
wanted to display as a string
01:15:36
the reason this is a string and not like
01:15:38
a date or a long or something
01:15:40
is these are kind of my lowest level
01:15:43
view components so they should be as
01:15:46
dumb as possible they shouldn't do any
01:15:48
sort of formatting or anything like that
01:15:51
that should be reserved for like a view
01:15:53
model or a presenter
01:15:54
by the time your data hits the view
01:15:56
layer it should be ready to display
01:15:60
um so i'm just assuming that will be
01:16:02
formatted for me
01:16:03
and then i said hey show me some text
01:16:07
give it a style if i want to add this to
01:16:11
i can just add the receipt time
01:16:17
that's my header so i actually need to
01:16:20
pass in the receipt time to my header
01:16:28
that here we go then i need to pass in
01:16:31
the receipt time
01:16:35
space that out a little bit it's a
01:16:37
little easier to see rebuild that
01:16:40
and that should display the receipt time
01:16:43
my sender text which it does but
01:16:46
everything's a little bit squished
01:16:47
together um so there's a couple reasons
01:16:50
number one the row assumes that it only
01:16:53
is kind of a wrap content
01:16:55
width so it's kind of squishing
01:16:57
everything together
01:16:58
so what you can do to modify that is
01:17:02
there's a modifier argument on pretty
01:17:05
much every composable
01:17:07
function so modifiers are how you add
01:17:11
padding setting the size of something
01:17:14
filling up the space so that's what i'm
01:17:18
so i can say hey please have this row
01:17:20
fill up the max width
01:17:22
uh so it'll basically fill up its parent
01:17:25
uh so if i refresh the preview we'll see
01:17:27
that the row does in fact fill up all
01:17:30
not height there we go
01:17:33
fill up the width so that'll fill up the
01:17:37
but we still kind of have the same
01:17:38
problem in that the receipt time is
01:17:41
smushed up against the sender text
01:17:45
and how we fix this is we need to
01:17:47
provide a modifier to the sender
01:17:49
to tell it to take up the full width or
01:17:52
the remaining space so i'm going to need
01:17:55
another parameter here and
01:17:58
inside of the row this lambda basically
01:18:01
is all of the child views you want
01:18:03
inside of your row
01:18:04
but specifically this is a row scope
01:18:06
which you can kind of see from this hint
01:18:09
now the row scope defines some custom
01:18:13
one of which is a weight so this
01:18:16
basically says hey
01:18:17
sender please take up whatever remaining
01:18:21
i need to provide the actual modifier
01:18:25
and i want to go ahead and provide a
01:18:26
default just in case
01:18:29
um so my sender doesn't have to be used
01:18:32
if it doesn't need to be
01:18:36
so providing this weight to the sender
01:18:38
will basically force it to take up
01:18:40
remaining space is left if it'll work oh
01:18:43
i need to actually apply the modifier
01:18:49
there we go so once the modifier is
01:18:51
applied to the sender the text will
01:18:53
basically expand out
01:18:54
as far as it can and push the receipt
01:18:57
time all the way over to the right
01:18:59
which is great so that's kind of the
01:19:04
next i'm going to focus on building out
01:19:05
the actual email view itself
01:19:08
so the next thing is the header is
01:19:10
stacked on top of the subject and body
01:19:14
so in the header i used a row to
01:19:17
stack things as a row fortunately
01:19:20
column that i can use to stack things
01:19:24
so we say hey have an email header
01:19:28
pass in a subject
01:19:35
uh now these like the receipt text
01:19:38
there's nothing super exciting going on
01:19:40
uh it's just declaring a text setting
01:19:44
setting a font size and a color uh the
01:19:46
body is actually a carbon copy of the
01:19:49
um so nothing too much to look into
01:19:54
but you get to see the preview refresh
01:19:58
actually see it displayed in a column so
01:19:60
we have things kind of getting
01:20:02
the email views coming together at this
01:20:05
next is we need the little star to show
01:20:09
and if you look closely the star is
01:20:12
actually in a row
01:20:13
with the subject and body text because
01:20:15
they're both ellipse sized
01:20:18
so the subject and body are in a column
01:20:21
because they're vertical and then that
01:20:23
is inside of a row
01:20:24
so that the star can be in the right
01:20:26
place so i can add this stuff
01:20:32
add a column we'll dump the subject and
01:20:35
body text into here
01:20:38
and then i need a star to go in the row
01:20:44
so i have that so say email.starred
01:20:48
uh the star at this point is very
01:20:51
the uh important icon it's loading a
01:20:55
uh it's getting tinted uh the only
01:20:58
difference is i'm modifying the color
01:21:00
of the star based on if the email has
01:21:03
been starred or not
01:21:05
so i can just use this if logic thanks
01:21:08
kotlin for not having me
01:21:10
set that twice but once i run the star
01:21:14
you see kind of a similar thing so the
01:21:18
uh smushed over up against the subject
01:21:22
because they are only taking up as much
01:21:24
space as they need
01:21:26
so i need to go back and have the column
01:21:28
take up plenty of space
01:21:30
so we'll use that modifier weight trick
01:21:35
and another thing is the star needs to
01:21:37
be in the bottom over here
01:21:39
so in a similar trick we can use the
01:21:43
actually the vertical alignment or
01:21:47
say align the star to the bottom or
01:21:50
align the row to the bottom rather
01:21:53
the subject and body are not going to be
01:21:54
impacted by that because they're already
01:21:56
taking up the full height
01:21:57
but the star will get pushed down to the
01:22:01
now another thing that needs to happen
01:22:03
is the star needs to be clickable
01:22:05
uh because right now it's not responding
01:22:08
to any kind of click events
01:22:10
so what i can do is
01:22:13
uh the star needs to basically take in a
01:22:17
and fire off the listener when it gets
01:22:20
um so we can just say
01:22:24
like add an on click lambda no
01:22:30
doesn't return anything this is your
01:22:31
typical click listener
01:22:34
here and then you can wrap
01:22:37
your icon in an icon button
01:22:59
maybe it's just mad no
01:23:08
oh there we go so we basically just say
01:23:13
the button adds a clickable interface
01:23:15
around our icon so it'll fire
01:23:18
the click listener whenever it gets
01:23:19
tapped so that i then need to
01:23:22
provide a click listener here
01:23:25
this brings up another question
01:23:28
my email currently is immutable because
01:23:31
it's a data class but everything is a
01:23:33
so i can't set any of this data
01:23:37
so what if i need to there's a couple
01:23:39
ways of dealing with state
01:23:41
in compose one way is you can update
01:23:44
your property to a var if you need the
01:23:47
and then say hey this is a model so you
01:23:50
add the model annotation
01:23:52
what this does is whenever a composable
01:23:56
function takes in a model anytime
01:23:60
it accesses the properties of that model
01:24:03
is registered to observe changes to
01:24:06
those properties
01:24:07
so since i'm passing in the starred
01:24:10
property my email view will update if
01:24:13
the property changes
01:24:18
so what i can do is
01:24:23
oh i actually need a property here so
01:24:26
what i can do instead
01:24:28
this is a better example so instead of
01:24:32
what you can do is there's a toggleable
01:24:36
that you can do so instead of just
01:24:37
responding to a click
01:24:39
toggleable is basically a click with a
01:24:42
so we could say uh it needs the initial
01:24:46
um and there's an on value change
01:24:51
uh this is different because on value
01:24:53
change requires a boolean so this is the
01:24:55
on and off so we'll just update that
01:24:60
so now our star can modify its color
01:25:03
based on the start
01:25:04
uh the onstar click and we should be
01:25:07
able to react to it
01:25:09
uh this is gonna be mad because i need
01:25:13
but i can update my email and
01:25:16
this should be happy
01:25:20
so i can try to run the app over here on
01:25:25
uh so we get my little email list and
01:25:27
when i click on the star
01:25:29
it updates uh which is cool it does work
01:25:33
another option you have if you don't
01:25:37
class here you can keep everything
01:25:41
but you would need to wrap your
01:25:44
uh property in something called a
01:25:50
um so this is basically saying hey this
01:25:53
state instead of the email itself and
01:25:57
pull out the email from the state
01:26:01
now accessing the value of a state works
01:26:03
similarly to your model
01:26:05
any changes made to the state are going
01:26:08
to cause your view to recompose
01:26:10
it's just a little bit more complex i'll
01:26:13
need a new email
01:26:17
fortunately since i'm using the data
01:26:22
i can just copy it and override the
01:26:24
fields i want and then i can set the
01:26:28
like so that will cause it to
01:26:31
update my email preview needs an update
01:26:35
because it's still expecting an email
01:26:37
so if you need a state
01:26:41
there's a mutable state of function
01:26:45
and that'll basically wrap your model
01:26:47
object in a state
01:26:49
you pass that along uh i'll need this
01:26:51
same logic in my activity
01:26:53
to actually run the thing
01:26:56
so i'm now passing in a state instead of
01:26:59
the email itself and
01:27:03
i can still update the star so it's
01:27:06
still responding to clicks
01:27:08
and it's still updating my view state i
01:27:11
like this a little bit more
01:27:12
uh just because it makes me be very um
01:27:16
explicit about state updates instead of
01:27:18
having like a mutable class
01:27:20
but that's kind of a personal preference
01:27:24
um so in the interest of time
01:27:28
i think we'll keep this about where it
01:27:31
i'll actually just add some padding
01:27:35
uh let's do 16 dips
01:27:39
um so that will just add some padding
01:27:42
around my email view
01:27:44
just to be a little bit more material
01:27:45
and make it look a little bit nicer
01:27:48
so there we go got some padding so
01:27:51
that's the email
01:27:52
view so it's fairly easy to build all of
01:27:56
from the bottom up if you want to
01:27:60
i'm going to make another composable
01:28:01
function called email list that takes in
01:28:04
a list of emails and if y'all are
01:28:07
familiar with android you
01:28:08
probably know about recyclerview and
01:28:12
bit of pieces that you need to kind of
01:28:13
put together fortunately making a list
01:28:16
in compose is a lot easier
01:28:18
you just use this adapter list thing
01:28:21
that's in your list of items
01:28:22
and then you just provide this lambda
01:28:25
which is the child it passes in
01:28:29
each item that needs to basically render
01:28:34
so similar to recyclerview it'll only
01:28:35
request the items it actually needs to
01:28:39
i'll make a statement
01:28:43
and then i can return the uh
01:28:51
recyclerview would probably be a lot
01:28:53
more code in this case
01:28:54
it's four lines of code i can go over to
01:28:57
my main activity
01:28:59
i have a little function to generate my
01:29:06
uh let's see list
01:29:12
so i get my email list i'll create a
01:29:21
and then i'll do the email list
01:29:25
actually i don't need a state here i
01:29:26
just need the list makes that a little
01:29:30
and i can run the app and it will
01:29:33
show the list there we go
01:29:37
so we have the list here uh performance
01:29:40
great if i'm honest it's fairly clunky
01:29:44
it's a little slow um so that's one
01:29:47
another issue is that the um
01:29:50
the state updates do not currently work
01:29:53
with adapter list so that's that's a
01:29:54
really big issue
01:29:56
um i've tried to fix this by moving the
01:29:58
state up to the email list and then
01:30:00
having the email list recomposed but
01:30:02
that didn't work either
01:30:04
so there's currently a bug ticket open
01:30:07
and the compose folks are working on it
01:30:10
soon it'll be good
01:30:14
but it is what it is for now
01:30:17
um so next i wanna app bar
01:30:21
up at the top um so i just have an email
01:30:24
app bar composable
01:30:26
uh the component you're gonna wanna use
01:30:27
is the top app bar
01:30:29
uh there's also a bottom at bar if you
01:30:31
want bottom navigation
01:30:32
uh you just need to provide things like
01:30:34
a title uh navigation icon if you want
01:30:37
actions if you need those um so maybe my
01:30:42
uh i don't know faux mail because it's
01:30:46
my navigation icon i can use an icon
01:30:49
button for this one
01:30:52
wrap this in an icon
01:31:01
and we'll just leave the actions out for
01:31:05
so this will basically make a toolbar
01:31:07
for the top of your app
01:31:08
uh it'll provide your little navigation
01:31:10
icon on the left
01:31:11
the title right next to it uh when you
01:31:14
add these things all together you could
01:31:18
make it yourself like put everything in
01:31:20
a column and do all that but
01:31:22
fortunately there's a better way so
01:31:25
typically what you'll want to do is
01:31:27
you'll want to make a
01:31:28
composable function specifically for
01:31:31
so in this case i have an email list
01:31:33
screen composable
01:31:36
takes in my list of emails takes in some
01:31:38
navigation items which i'll get to in a
01:31:40
but you're going to use a scaffolds now
01:31:43
the scaffold is the thing
01:31:44
that kind of puts everything together so
01:31:48
your app bar uh in the top app bar
01:31:51
and then the last lambda is the body so
01:31:54
this is just whatever
01:31:56
um you need to display in the
01:31:60
so if i update my app to do the
01:32:04
screen i'll pass in the list and i also
01:32:06
have a function to generate navigation
01:32:08
just so that works
01:32:10
this will show you the top app bar at
01:32:12
the top of the screen
01:32:17
so you got your toolbar you can modify
01:32:20
however you want you can provide like
01:32:22
custom views inside
01:32:24
for the text and everything so
01:32:28
it's really up to you what you want to
01:32:31
scaffold has a lot of other stuff that
01:32:34
most notably is the navigation drawer
01:32:38
so this is a rather large class
01:32:42
which is all for my email navigation
01:32:45
um so it uses an adapter list it has a
01:32:48
sealed class to represent the different
01:32:52
it sort of switches across those and
01:32:54
returns the different
01:32:55
uh composable functions that are needed
01:32:58
um i have a preview in here so i can
01:33:01
actually show you what that will look
01:33:03
the actual preview that'll get displayed
01:33:07
i have a link to all this so i can post
01:33:10
um but in your scaffolds
01:33:20
uh you pass in some drawer content uh so
01:33:23
this is where you want your email
01:33:27
uh pass in the nav items um
01:33:31
and one other thing you're gonna need is
01:33:33
uh you're gonna need some state
01:33:43
so there's a different way to make state
01:33:45
so you can use this state
01:33:46
lambda this is a way of a shorthand way
01:33:48
of making a mutable state
01:33:52
but the scaffold specifically needs a
01:33:55
so this is uh like is the drawer open or
01:34:00
and can you use gestures to open the
01:34:04
so so far we have gestures enabled and
01:34:07
we just need to pass this
01:34:10
to the scaffolds
01:34:14
now this states what it does that's
01:34:16
different from before
01:34:17
is it not only returns the state itself
01:34:19
but it returns a
01:34:21
listener function so you can use that
01:34:23
kind of as an easy way of
01:34:25
updating but i should be able to use
01:34:28
my gesture to open the drawer it
01:34:32
goes up and down so looks good
01:34:35
swipe it closed not going to
01:34:38
deal with the nav icon quite yet check
01:34:42
out the code if you want to see how that
01:34:46
i think the last thing i wanted to show
01:34:47
uh is probably everybody's favorite
01:34:49
material button which is the
01:34:51
floating action button uh so there's a
01:34:54
floating action button
01:34:55
class you can use takes an on click
01:34:58
you can throw an icon in it and it works
01:35:01
uh you can also use text
01:35:03
if you want or realistically any uh
01:35:06
it might just look a little bit weird if
01:35:07
it's like too large or something
01:35:10
but all this really does is give you the
01:35:11
style of a floating action button
01:35:14
it grabs the primary color from your
01:35:15
theme makes it circular
01:35:18
and stuff like that when you want to use
01:35:22
you just add the floating action button
01:35:26
say new email button um not gonna
01:35:29
respond to clicks just yet but this will
01:35:32
add it to the scaffold it'll position it
01:35:36
right of the screen and it gets you
01:35:40
little ripple animations there's also a
01:35:44
if you want um which one is it
01:35:49
so there's a the scaffold has a fab
01:35:51
position you can center it
01:35:53
if you want um if that's what your
01:35:55
design works with
01:35:58
so it'll just go right there there's
01:36:01
center docked and end docked so the
01:36:04
scaffold also will work with a
01:36:06
bottom navigation and the dock will
01:36:09
basically like cut out
01:36:11
the bottom navigation uh for the
01:36:14
floating action button so
01:36:15
if you want that in your design it's
01:36:17
pretty much included
01:36:18
by default in jetpack compose
01:36:24
so uh that is pretty much my demo
01:36:28
um let me see uh
01:36:31
if you do want the code for this um i
01:36:34
have a bitly link
01:36:35
here just jet back dash compose dash
01:36:39
uh this will link you to the github repo
01:36:42
where the code is i included a little
01:36:44
bit of information
01:36:45
about myself as well as a bunch of links
01:36:48
for if you're interested in learning
01:36:50
about jetpack compose um one great
01:36:54
there the kotlin lang slack if you're in
01:36:56
there there's a compose channel which is
01:36:59
um there's some google folks in there so
01:37:00
it's really easy to get feedback
01:37:03
like see what's new what's uh working
01:37:06
and they are very open to bug tickets so
01:37:08
if you find bugs please report them
01:37:11
uh next uh about me
01:37:15
so again i'm brian gardner uh i
01:37:19
you can follow me on twitter if you like
01:37:22
check out my website i've been doing a
01:37:24
blog series about jetpack compose
01:37:26
i think there's about 10 articles
01:37:27
currently so if you want a little bit
01:37:29
more in-depth information you can check
01:37:33
also again i work for big nerd ranch uh
01:37:36
consulting android consulting ios
01:37:39
a lot of you all probably know us from
01:37:43
um i'm actually the co-author on the
01:37:46
android programming guide um so check
01:37:49
that out there's a lot of jetpack
01:37:50
goodness in there and we teach classes
01:37:53
so uh hit us up if you're interested
01:37:57
uh but thanks for watching
01:38:00
brian fantastic job thank you so much
01:38:03
with us today it was really exciting to
01:38:06
in action and and the way you presented
01:38:08
that uh i'm pretty sure if anybody's
01:38:10
like me they were pretty much glued to
01:38:12
the screen the entire time
01:38:13
loved it thank you so much for doing
01:38:15
that you're about to play question
01:38:17
roulette as well
01:38:19
uh and so we've got uli showing the
01:38:22
of the most popular question so i'm
01:38:23
going to let you fire away on that
01:38:26
yeah uh so top one what have you found
01:38:28
to be the benefits of compose versus xml
01:38:31
um i think the biggest benefit is xml
01:38:35
is like i'm not a big fan like it works
01:38:38
don't get me wrong i tried onco when it
01:38:40
came out with the like json style
01:38:43
stuff um and it wasn't great i like
01:38:45
being able to have
01:38:46
like autocomplete in there you can
01:38:50
the documentation for uh like the text
01:38:54
say you can see all right what exactly
01:38:56
are all of the properties that this
01:38:58
i don't have to go to
01:38:60
developer.android.com
01:39:02
and look up the documentation it's just
01:39:05
a very fluent interface
01:39:06
i like it a lot more than xml i think
01:39:09
it's a lot cleaner
01:39:10
yes you're going to have a lot more
01:39:12
kotlin code in there because you're
01:39:14
going to have to
01:39:15
create all of your views in kotlin
01:39:18
but i think it's kind of worth it
01:39:20
because you're you have you're gaining
01:39:22
kotlin code but you're losing
01:39:23
xml so i'm a fan
01:39:27
um let's see mobile development is
01:39:29
shifting to declarative uis flutter
01:39:31
swift ui and compose
01:39:32
how mature do you see composed let's say
01:39:36
um i don't see it being release or
01:39:39
production ready
01:39:40
in one year maybe beta if we're lucky
01:39:44
um i'm hoping it goes alpha
01:39:47
a little bit later this y