← Tuesday, December 6 | Today, December 8 →
Dec 7 | 7:25 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Steve S. | has entered the room |
Mark M. |
hello, Steve!
|
Steve S. |
Hi Mark!
|
Mark M. |
how can I help you today?
|
Steve S. |
I have a follow-up question from yesterday:
|
Steve S. |
View paste
|
Steve S. |
I'll also paste in ContactsCache to refresh your memory:
|
Steve S. |
View paste
|
Mark M. |
"I probably shouldn't do that since there is a chance that ContactsCache.getContacts() would have to retrieve the contacts from the database rather than an in-memory static variable" -- well, if you already are showing data in the list, that data will already be in the cache
|
Steve S. |
ok
|
Mark M. |
you might still want your List<Contact>, just because that represents the view on the data that the user is working with
|
Mark M. |
(e.g., filtered search results)
|
Steve S. |
ok
|
Steve S. |
but at present it will be exactly the same as what's in the cache.
|
Mark M. |
not necessarily, depending on how you are dealing with asynchronous operations (e.g., network I/O)
|
Dec 7 | 7:30 PM |
Mark M. |
however, you are correct that you need to be able to deal with cache misses
|
Steve S. |
ok
|
Mark M. |
you already have some logic for loading your data asynchronously (I hope)
|
Mark M. |
that just turns into stuff to populate your cache
|
Steve S. |
ok
|
Steve S. |
i manage the data from an IntentService. It both communicates with the back-end and adds and deletes items from the database.
|
Steve S. |
that's also where i'm at present updating the cache.
|
Steve S. |
and calling ContactsCache.getContacts()
|
Steve S. |
my plan at present is to use EventBus to send updated lists of contacts to the fragment and have the fragment update the ListView
|
Mark M. |
so, pass the List<Contact> in the event
|
Steve S. |
yes
|
Mark M. |
and after a configuration change, call peekContacts() or something on your cache, to either get the List<Contact> or null
|
Mark M. |
and if it is null, scratch your head, wonder where the contact data went, shrug your shoulders, and tell your IntentService to get busy
|
Dec 7 | 7:35 PM |
Mark M. |
and 99.999% of the time, peekContacts() will return the List<Contact> without issue
|
Steve S. |
i'm using a retained fragment to preserve List<Contact> across configuration changes
|
Mark M. |
since it was just a configuration change, and in your current cache setup, the data simply can't get lost
|
Mark M. |
yes, but I thought your question was whether you should still do that
|
Mark M. |
you can, if you want
|
Steve S. |
yes, you're right
|
Steve S. |
so it would be reasonable to handle occasional (but rare) cache misses on the UI thread?
|
Mark M. |
no
|
Mark M. |
because that will freeze the UI
|
Steve S. |
ok, that was my concern
|
Mark M. |
however, your current cache is effectively an all-or-nothing affair
|
Steve S. |
ok
|
Mark M. |
once loaded, the only way your cache goes away is if your whole process does
|
Mark M. |
now, given Android's task stuff, you can't assume that the user is always coming into your process through the launcher activity
|
Steve S. |
ok
|
Mark M. |
you need to be in position to request that the data be loaded, in the case that it is not available
|
Mark M. |
however, ideally, that's not significantly different than what happens when the user launches the app normally
|
Mark M. |
and you're already handling that case by one means or another
|
Steve S. |
right, i'm using the IntentService for that
|
Dec 7 | 7:40 PM |
Mark M. |
so, if your retained fragment gets to onViewCreated() or whatever and realizes that the retained list is null, you need to peek into your cache to see if you have the data there
|
Mark M. |
in your current architecture, the answer should be no, unless I'm forgetting some scenario
|
Mark M. |
and so if your fragment doesn't have the data, and the cache doesn't have the data, you kick off the IntentService to go get the data
|
Steve S. |
ok
|
Mark M. |
personally, because of the need to use things like an IntentService, I'm not a huge fan of getContacts() doing the lazy load itself
|
Mark M. |
the cache should be pretty much just that: a cache
|
Steve S. |
so what you meant by peekCache() is a method that checks to see if the static member variable that holds the contacts is null?
|
Mark M. |
or something along those lines, yes
|
Steve S. |
ok
|
Mark M. |
(BTW, don't forget to use AtomicReference or concurrent collections or something to deal with thread safety)
|
Mark M. |
now, if you change the cache to be just a cache, and move the data-load logic elsewhere, it could be that getContacts() itself is now a non-blocking call
|
Mark M. |
and you don't need another separate peekContacts() method or some such
|
Steve S. |
ok. so i would load the data from the database from somewhere else and then have a method like ContactsCache.update() to set the static member variable?
|
Mark M. |
yes
|
Steve S. |
ok
|
Mark M. |
(or setContacts(), for parallelism)
|
Steve S. |
right
|
Dec 7 | 7:45 PM |
Steve S. |
getting back to AtomicReference/concurrent collections: if I only set the ContactsCache static member variable from the IntentService, would I still need to worry about that?
|
Mark M. |
yes
|
Steve S. |
ok
|
Mark M. |
at least use AtomicReference
|
Mark M. |
to basically ensure an atomic swap of List<Contact>
|
Steve S. |
i see
|
Mark M. |
assuming that the service is always building a complete new List<Contact> every time
|
Steve S. |
that's what i have now
|
Mark M. |
that's simple on the threading standpoint
|
Steve S. |
ok
|
Mark M. |
it generates more garbage for the garbage collector
|
Mark M. |
as with everything, there are trade-offs to be made
|
Steve S. |
sure. so more garbage collection activity vs a simpler threading approach
|
Mark M. |
right
|
Mark M. |
and, in the short term, that's probably a fine tradeoff
|
Steve S. |
ok
|
Dec 7 | 7:50 PM |
Steve S. |
now if use something like peekCache(), I'll still need to have logic to handle updating the cache using the IntentService
|
Mark M. |
yes
|
Steve S. |
so i'll still need to have message passing between the activity/fragment and the intentService to handle cache misses
|
Mark M. |
from the IntentService to the activity/fragment, yes
|
Mark M. |
the activity/fragment would start the IntentService on a cache miss
|
Steve S. |
so it's not really going to give me the simpler architecture i had naively hoped for - but it could work more smoothly
|
Mark M. |
the more useful the app, the less likely it is that it will have a simple architecture
|
Steve S. |
right. the first version was much clunkier and much easier to write.
|
Steve S. |
ok. there's a lot of material to chew on. i'll think things over.
|
Steve S. |
no more questions today - thank you so much!
|
Dec 7 | 7:55 PM |
Steve S. |
have a good rest of the day!
|
Mark M. |
you too!
|
Steve S. | has left the room |
Dec 7 | 8:25 PM |
Mark M. | turned off guest access |
Dec 7 | 8:50 PM |
Mark M. | has left the room |
Dec 8 | 8:55 AM |