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.
|
Steve S. |
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.
|
Steve S. |
Here's the cache:
|
Steve S. |
View paste
|
Steve S. |
You had mentioned using AtomicReference, which I've tried to do.
|
Dec 15 | 7:30 PM |
Mark M. |
if you are planning on replacing the entire list outright, this is a good plan
|
Steve S. |
ok
|
Steve S. |
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
|
nat |
I get : enqueue retrofit2.Callback in call cannot be applied to anonymous
|
nat |
any ideas?
|
Mark M. |
um, not really, other than perhaps you have something else named Callback
|
nat |
ok, will look again into the code
|
nat |
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
|
Mark M. |
go ahead with your second question, then I'll turn back to Steve for a bit
|
nat |
Trying to get a similar layout https://github.com/rubensousa/RecyclerViewSnap/...
|
nat |
thinking about NestedScrollView with RecyclerView
|
nat |
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?
|
Mark M. |
I think the conventional approach for that look nowadays is nested RecyclerViews
|
Dec 15 | 7:35 PM |
Mark M. |
actually, that repo is a sample app, not a library -- my apologies
|
Mark M. |
but, that sample app should show you the nested-RecyclerView approach
|
nat |
Ok, because that app uses coordianator + nestedScrollView + recycler
|
nat |
that would be ok?
|
nat |
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
|
nat |
yeah, not too many
|
Mark M. |
wait
|
Mark M. |
so that app is using a NestedScrollView around a vertical RecyclerView?
|
Mark M. |
I suppose that works
|
Mark M. |
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
|
Mark M. |
that feels better
|
Mark M. |
if there's only a few things on the vertical axis, that approach is fine
|
nat |
cool, just wanted to run that by you
|
nat |
got it
|
Mark M. |
but if there might be dozens or more, then a vertical RecyclerView would be worth considering
|
Mark M. |
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?
|
Dec 15 | 7:40 PM |
Steve S. |
i need a class that will pass a List<Contact> via an EventBus event.
|
Steve S. |
here's a possible design:
|
Steve S. |
View paste
|
Steve S. |
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
|
Mark M. |
your other thread (e.g., main application thread) gets the event from the bus
|
Mark M. |
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
|
Steve S. |
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
|
Mark M. |
now, if your event publisher decides to keep poking at that event object after posting it, *then* you have coordination problems
|
Mark M. |
with your cache, everybody has access to it, because it is global in scope
|
Mark M. |
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>
|
Dec 15 | 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
|
Mark M. |
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
|
Mark M. |
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
|
Mark M. |
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
|
Dec 15 | 7:50 PM |
Mark M. |
to the point where you might have the *cache* be the one to post the event
|
Dec 15 | 7:50 PM |
Mark M. |
but, let's turn to nat
|
Mark M. |
nat: your turn! do you have another question?
|
nat |
but what's your choice of a server for background recurrent actions
|
nat |
like tweeting
|
nat |
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
|
nat |
yeah
|
Mark M. |
I have never used Spring
|
nat |
Java code
|
nat |
or tomcat
|
Mark M. |
in terms of infrastructure, I use Linode for durable servers
|
Mark M. |
though plenty of folk use AWS EC2
|
Mark M. |
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
|
Mark M. |
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
|
Mark M. |
but, I'm old school
|
nat |
yeah, makes life easier
|
nat |
got ya
|
Mark M. |
sorry that I couldn't be of more help on that
|
nat |
thanks
|
Dec 15 | 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
|
Steve S. |
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
|
Mark M. |
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
|
Mark M. |
both is ove |