Office Hours — Today, December 15

Tuesday, December 13

Dec 15
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 some questions following up on the last time we chatted.
I'm designing a cache class that can be accessed from multiple threads and a class that can be passed using Greenrobot EventBus. Wondering if I'm on the right track.
Here's the cache:
View paste
public class ContactsCache {
    static private AtomicReference<List<Contacts>> sAtomicRef = new AtomicReference();

    static public List<Contacts> getList() {
        return sAtomicRef.get();
    }

    static public void setList(List<Contacts> c) {
        sAtomicRef.set(c);
    }
}
You had mentioned using AtomicReference, which I've tried to do.
7:30 PM
Mark M.
if you are planning on replacing the entire list outright, this is a good plan
Steve S.
ok
that is what i was thinking, for simplicity
nat
has entered the room
Mark M.
(BTW, hello nat -- I will be with you shortly!)
Steve S.
i can show you the other piece of code, though you might want to get to nat first
Mark M.
OK, no problem
nat
hi Guys
Steve S.
hi
Mark M.
nat: it's your turn already! how can I help you today?
nat
Mark I I'm using retrofit2
I get : enqueue retrofit2.Callback in call cannot be applied to anonymous
any ideas?
Mark M.
um, not really, other than perhaps you have something else named Callback
nat
ok, will look again into the code
I have another question if I can
Mark M.
it feels like the compiler is thinking perhaps that you are referring to some other Callback class, either one of yours or something else named Callback that you imported
go ahead with your second question, then I'll turn back to Steve for a bit
nat
thinking about NestedScrollView with RecyclerView
would that be what you would do?
Mark M.
well, considering that your GIF is from a library that handles this, why not use that library?
I think the conventional approach for that look nowadays is nested RecyclerViews
7:35 PM
Mark M.
actually, that repo is a sample app, not a library -- my apologies
but, that sample app should show you the nested-RecyclerView approach
nat
Ok, because that app uses coordianator + nestedScrollView + recycler
that would be ok?
any less complicated approach?
Mark M.
oh, the outer part is a NestedScrollView?
nat
yep
Mark M.
I mean, that'll work, assuming that the number of rows is modest
nat
+ vertical recycler + horizontal recycler
yeah, not too many
Mark M.
wait
so that app is using a NestedScrollView around a vertical RecyclerView?
I suppose that works
since there's no FAB and no fancy toolbar shenanigans, I'm not sure what the CoordinatorLayout and NestedScrollView is providing there
nat
scroll for vertical , recycler for horizontal, sorry
Mark M.
ah, OK
that feels better
if there's only a few things on the vertical axis, that approach is fine
nat
cool, just wanted to run that by you
got it
Mark M.
but if there might be dozens or more, then a vertical RecyclerView would be worth considering
just due to memory footprint
nat
ok, for now just 5 verticals
Mark M.
let me switch back to Steve, and I'll return to you in a bit if you have further questions
nat
thanks, go ahead
Mark M.
Steve: your turn! do you have another question?
7:40 PM
Steve S.
i need a class that will pass a List<Contact> via an EventBus event.
here's a possible design:
View paste
public class ContactsRefreshEvent {
    final private AtomicReference<List<Contact>> mAtomicRef;

    public ContactsRefreshEvent(List<Contact> c) {
        mAtomicRef = new AtomicReference<>(c);
    }

    public List<Contact> contacts() {
        return mAtomicRef.get();
    }
}
i thought i would again need AtomicReference since the list is accessed from two different threads.
Mark M.
you probably don't need the AtomicReference here
Steve S.
really
Mark M.
yes, but they aren't going to do so simultaneously, assuming fairly normal EventBus usage
Steve S.
ok. but what about visibility?
Mark M.
typically, the background thread creates the event, puts it on the bus, and then never touches that List<Contact> instance again
your other thread (e.g., main application thread) gets the event from the bus
in that handoff, there isn't a case where the event object could be used by both threads at the same time
Steve S.
ok. so this is different from the cache case since List<Contact> is passed as an argument?
Mark M.
no, it is different because the event bus is handling inter-thread coordination, whereas your cache has to do that itself
Steve S.
i see
so i can rely on the event bus to do the synchronization
Mark M.
it's more that you can rely on the event bus to get the event to the other thread
Steve S.
ok
Mark M.
so long as your event publisher stops touching the event after posting it, you are OK
now, if your event publisher decides to keep poking at that event object after posting it, *then* you have coordination problems
with your cache, everybody has access to it, because it is global in scope
and so multiple threads could hit it, pretty much by definition
Steve S.
ok. the event publisher will change List<Contact> but will then send another event with the new List<Contact>
7:45 PM
Mark M.
you lost me there
Steve S.
sorry. i mean the event publisher will create a new List<Contact>. when it does, it will send another event to the subscriber
Mark M.
um, yes, I think, though I don't know all that much about your app in the end
Steve S.
ok
Mark M.
note that since you have the cache, you could also dispense with passing the List<Contact> itself in the event
the event would just be an empty object, signalling "yo, the data changed, grab a fresh list from the cache"
Steve S.
that's true, but wouldn't i then have to account for the case where the process got killed and restarted, leaving the cache empty?
Mark M.
if the process is killed, your events are gone
Steve S.
ok
Mark M.
my assumption is that you are updating the cache, then posting the event saying we have new contacts
Steve S.
that's right
Mark M.
in that case, the cache already has the new contacts, and the event recipient can get them from the cache
and if the process goes "poof" in the microseconds between posting the event and receiving the event, life goes on
Steve S.
ok. so it sounds like i can safely assume that if the event is received, then the cache has the data.
Mark M.
let me take another question from nat, and I'll come back to you in a bit
yes
Steve S.
sure
Mark M.
assuming you update the cache before posting the event
Steve S.
ok
nat
Mark, this is a bit not related
7:50 PM
Mark M.
to the point where you might have the *cache* be the one to post the event
7:50 PM
Mark M.
but, let's turn to nat
nat: your turn! do you have another question?
nat
but what's your choice of a server for background recurrent actions
like tweeting
is AWS linux with Jenkins a good choice
Mark M.
you mean, for a Twitter bot?
nat
or would you go for a full fledged Spring server
yeah
Mark M.
I have never used Spring
nat
Java code
or tomcat
Mark M.
in terms of infrastructure, I use Linode for durable servers
though plenty of folk use AWS EC2
I use those just for transient work, like publishing book updates
nat
OK, will look into that
Mark M.
in terms of server-side code, I tend towards far lighter-weight frameworks, mostly involving Ruby
nat
any ideas on serverless stuff like AWS lambda?
Mark M.
I've heard of Lambda but haven't really looked at it
nat
ok, got it
Mark M.
I'm enough of a control freak that I prefer having (virtual) iron of my own
rather than, say, Heroku-style "upload an app and we'll kinda figure it out"
nat
:-) , that is working well as I see
Mark M.
I've been meaning to get into containers (e.g., Docker) but haven't invested the time yet
but, I'm old school
nat
yeah, makes life easier
got ya
Mark M.
sorry that I couldn't be of more help on that
nat
thanks
7:55 PM
Mark M.
let me turn back to Steve, and I'll swing back to you a little later
nat
cool
Mark M.
Steve: your turn! do you have another question?
Steve S.
it does seem like it would be cleaner to just use the cache and dispense with passing the list via the event bus
what was your suggestion about having the cache send the event? so the cache would call EventBus code?
Mark M.
well, if you want your UI or other parties to know when the cache is updated, it stands to reason that the cache would be the one to tell them that the cache is updated
Steve S.
right. i hadn't thought of that but it does make sense
nat
has left the room
Steve S.
so i'll work on modifying setContacts() so after setting the static member field, it posts an event.
Mark M.
right
your service just has to update the cache
Steve S.
right. is there any need to synchronize setContacts, or will using AtomicReference suffice?
Mark M.
do one or the other
both is ove