Nov 15 | 8:55 AM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Nov 15 | 9:20 AM |
Leora | has entered the room |
Mark M. |
hello, Leora!
|
Mark M. |
how can I help you today?
|
Leora |
Hi Mark!
|
Leora |
Actually this is my first time in...
|
Leora |
And I thought I would observe other ppl's questions in the meantime
|
Mark M. |
ah
|
Mark M. |
people usually only pop in here when they have a question
|
Leora |
Ok, got one for ya!
|
Mark M. |
right now, you're the only one here
|
Mark M. |
go right ahead!
|
Mark M. |
(though if the question is "will you retitle your book as 'Booky McBookface'?", the answer is no)
|
Mark M. |
:-)
|
Leora |
Ok, so I started implementing Room, had some annoying errors, and then gave up when I realized it would be problematic to save Lists as is, without manipulation
|
Mark M. |
you can pass List<YourEntity> into a @Dao class's @Insert, @Update, or @Delete method
|
Leora |
I know you have an entire pdf on it, but I'm torn between ppl who really really love it, and ppl who believe a new component has no place in production
|
Nov 15 | 9:25 AM |
Mark M. |
that then depends a lot on the definition of "new"
|
Mark M. |
the core Architecture Components shipped as a 1.0.0 a week ago
|
Mark M. |
prior to that, I would not have shipped it in production
|
Mark M. |
now, it's worth considering
|
Mark M. |
but Room is merely one candidate approach to simplifying database access
|
Mark M. |
it's going to be relatively popular, as it's from Google, and anything Googly gets outsized attention
|
Leora |
I dunno, some ppl wait for .1 !
|
Mark M. |
understood
|
Mark M. |
OTOH, it's not like you'll integrate Room in a few hours
|
Mark M. |
by the time you shipped something with Room, starting from (relative) scratch now, a 1.1 might well be out
|
Mark M. |
(or at least a 1.0.1)
|
Leora |
It's not that, it's in the process of researching my bugs, I found 2 answers, one was re kotlin and room, the other answred by you, the answered by....me!
|
Leora |
an hour ago haha
|
Mark M. |
it's always nice when your past self leaves notes for your future self :-)
|
Leora |
hahah
|
Leora |
so I can't query a list of objects?
|
Leora |
like
|
Leora | |
Leora |
List getAll()
|
Mark M. |
um, sure -- have it return List<TeaserItemEntity>
|
Drasko | has entered the room |
Mark M. |
or List<TeaserItemPOJO>
|
Mark M. |
(BTW, hello, Drasko -- I will be with you shortly!)
|
Drasko |
Hi, everybody!
|
Leora |
hmm...I have to research the syntax more
|
Nov 15 | 9:30 AM |
Leora |
Another question please - architectual
|
Mark M. |
let me take a question from Drasko first, and then I'll return to you
|
Leora |
Hi Drasko!
|
Mark M. |
Drasko: your turn! do you have a question?
|
Leora |
ok great
|
Drasko |
View paste
|
Mark M. |
hmmmm...
|
Mark M. |
to be honest, your scenario doesn't work all that well starting with Android 8.0
|
Mark M. |
the best solution that I can think of is an IntentService, but using startForeground()
|
Drasko |
I know, that's why I am asking you. :)
|
Mark M. |
otherwise, you may not get the APK downloaded before your service is stopped and your process is terminated
|
Mark M. |
JobIntentService gives you a bigger window, but that's for purely internal use -- you cannot readily have an outside app start one
|
Mark M. |
you could have a regular Service that gets exported, and all it does is turn around and start the JobIntentService, I suppose
|
Mark M. |
exported="true" won't be necessary, if you have an <intent-filter>
|
Drasko |
ok.
|
Mark M. |
and I recommend using an <intent-filter>, so if your updater app gets refactored or something, app A doesn't need to change references to classes and such
|
Nov 15 | 9:35 AM |
Drasko |
yes, you are right. I don't have experience with apps without any UI, so how could I make one in this scenario? (just the rough sketch would be enough)
|
Drasko |
don't need to go into details.
|
Mark M. |
um, just don't have an <activity>
|
Mark M. |
your app A would need to create an explicit Intent to start the service in the updater app
|
Drasko |
thnks
|
Mark M. |
for example, you could use PackageManager to find the component from the implicit Intent, then create an explicit Intent using that component
|
Mark M. |
I demonstrate this in the chapter on remote services and binding -- while I happen to demonstrate binding there, the explicit-Intent construction logic would work the same for a started service
|
Mark M. |
without the explicit Intent, your updater app would remain in the stopped state after installation, and it would not run
|
Mark M. |
note that I have not played with Knox, and so I do not know how it might impact any of this
|
Drasko |
yes, ok.
|
Drasko |
thank you very much.
|
Mark M. |
happy to help!
|
Mark M. |
let me take a question from Leora, and I'll return to you in a bit
|
Mark M. |
Leora: your turn! do you have another question?
|
Leora |
yay!
|
Nov 15 | 9:40 AM |
Leora |
if i'm adding fragments with replace, i want to know the best solution for temporarily storing server responses
|
Leora |
temporarily is about an hour
|
Leora |
and that's how i got into the whole room thing
|
Mark M. |
well, your process may not be around for an hour, so your thoughts on persisting the data make sense
|
Leora |
and if room/sqlite is the best way to handle storing arrays of objects
|
Mark M. |
whether you use SQLite, an ordinary file (e.g., JSON), or SharedPreferences, is up to you, though I lean towards not SharedPreferences
|
Mark M. |
arrays of objects typically result in their own table
|
Leora |
sharedprefs takes a lot of resources, no?
|
Mark M. |
not really, but it's designed mostly for simple name/value pairs, with an eye towards PreferenceScreen-based UIs
|
Mark M. |
it's not well-suited for arbitrary stuff
|
Mark M. |
you can shove arbitrary stuff in there, by converting the arbitrary stuff into JSON or XML or something
|
Leora |
yeah, so sqlite/ROOM vs file...what say you?
|
Mark M. |
that depends a lot on the situation
|
Mark M. |
for example, the right answer might be disk caching in your network API layer (e.g., OkHttp/Retrofit)
|
Mark M. |
or the right answer might be to use something like Store to handle the caching
|
Mark M. | |
Leora |
i can't cache on the network layer - that's what i wanted at first, cause they are https requests
|
Nov 15 | 9:45 AM |
Mark M. |
HTTPS shouldn't affect cacheability
|
Leora |
Retrofit doesn't support it :(
|
Mark M. |
um, OK
|
Mark M. |
that seems like a rather large hole
|
Leora |
it is! but then other devs answered me that duh! https shouldn't be stored
|
Mark M. |
um, the Web would be rather broken if that were true
|
Leora |
but i insisted that it's not login or anything, only content, so i'm cool
|
Mark M. |
no Web browser could cache anything
|
Leora |
hahaha
|
Mark M. |
yes, the issue isn't HTTPS, but the role of the page
|
Mark M. |
once upon a time, you might use HTTPS only for login
|
Mark M. |
not anymore
|
Mark M. |
regardless, "cache" to me implies a transient store, so that feels more like "serialize the stuff to JSON files" more than "roll a database"
|
Mark M. |
but, that's just a gut instinct
|
Mark M. |
again, the devil is in the details
|
Leora |
ok..... our app is a streaming app, similar to netflix, and i just want to store a list of 'media items' with their image url's, etc
|
Mark M. |
I'm not clear why that would be "cache" vs. "sync" (i.e., keeping the data locally more or less permanently)
|
Nov 15 | 9:50 AM |
Leora |
didn't understand that last part....
|
Mark M. |
you indicated earlier that you only wanted this data for an hour
|
Mark M. |
that seems short
|
Leora |
yes...content could change
|
Mark M. |
the items themselves (URL, images) are longer-lived
|
Mark M. |
the *role* might shift (e.g., what's promoted on some launcher activity)
|
Mark M. |
so, to me, that feels more like you should keep the data around (at least the small stuff) in a database, versus considering it to be stale after an hour
|
Mark M. |
only update what needs to be updated after the hour (e.g., new things, roles for existing things)
|
Mark M. |
and if you want to hold onto the data for a longer period of time, and the data kinda looks like tables, use SQLite (using Room or whatever)
|
Leora |
but i will still have to make a server call for the comparison...
|
Mark M. |
sure
|
Leora |
hmmm
|
Mark M. |
ideally, your server call gives you the delta: the changes that you need to apply
|
Mark M. |
or, your server call gives you a cheap index, for you to compute the delta and do the remaining calls (e.g., download missing images)
|
Leora |
haha...not in my workplace....that would be considered 'push' right?
|
Mark M. |
not really
|
Mark M. |
push would be "the server throws data at you when the data changes"
|
Mark M. |
pull does not imply that we're starting from scratch
|
Nov 15 | 9:55 AM |
Leora |
didn't understand the diff sorry
|
Nov 15 | 9:55 AM |
Mark M. |
push vs. pull isn't an Android concept
|
Mark M. |
it's more general than that
|
Mark M. |
let's use email as an example
|
Mark M. |
classic client-side email clients (i.e., not Web mail) could work on a push or a pull basis
|
Leora |
ok
|
Mark M. |
pull would involve asking the server every so often "hey, what's new in my inbox?"
|
Mark M. |
POP3 worked this way
|
Mark M. |
push would involve maintaining an open socket connection to the server, so the server can send down a message as soon as a new email arrives in the inbox
|
Mark M. |
IMAP4 works this way
|
Mark M. |
in Android terms, push is something like Firebase Cloud Messaging (FCM)
|
Mark M. |
pull is pull-to-refresh, AlarmManager-scheduled requests for server updates, etc.
|
Leora |
ahhh
|
Leora |
but the server is still aware of what the client received before
|
Mark M. |
ideally, yes
|
Leora |
mmmm
|
Mark M. |
based on a user account, or a timestamp, or a 'last-seen-UUID' value, or something
|
Leora |
wow thanks so much for that lesson!
|
Mark M. |
Drasko: sorry, I got caught up in Leora's questions -- do you have another question?
|
Leora |
ok great, i'll ask server side
|
Mark M. |
since we're running out of chat time
|
Leora |
one sec...so i could potentially use file json?
|
Drasko |
No, Mark, thanks. I am just following your conversation. :)
|
Leora |
hi!
|
Mark M. |
Drasko: OK
|
Nov 15 | 10:00 AM |
Mark M. |
Leora: sure, you can write JSON (using Gson, Jackson, or the JSON APIs in the Android SDK) to getFilesDir(), getCacheDir(), etc.
|
Leora |
Thank youuuuuuuuuuu
|
Mark M. |
and that's a wrap for today's chat
|
Leora |
You are a god-send and i can't believe i struggled these years alone!
|
Mark M. |
thanks for the kind words!
|
Mark M. |
the transcript will be posted to https://commonsware.com/office-hours/ shortly
|
Mark M. |
the next chat is tomorrow at 7:30pm US Eastern
|
Mark M. |
have a pleasant day!
|
Leora |
great :)
|
Leora | has left the room |
Drasko | has left the room |
Mark M. | turned off guest access |