Oct 11 | 7:25 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Oct 11 | 7:45 PM |
Aaron | has entered the room |
Mark M. |
hello, Aaron!
|
Mark M. |
how can I help you today?
|
Aaron |
hey Mark, I hope you are having a pleasant week. today I have one question about how to improve a certain piece of my app (with code, this time), another question about a specific bug, and maybe 1-2 more general questions if there is time
|
Mark M. |
OK
|
Aaron |
I'll go one at a time, the first one is a little lengthy but hopefully the explanation is helpful:
|
Aaron |
View paste
(4 more lines)
|
Mark M. |
this will take a moment
|
Aaron |
take your time
|
Oct 11 | 7:50 PM |
Mark M. |
postsLiveData is the source of the actual posts for the adapter?
|
Aaron |
correct
|
Mark M. |
and your concern is the // TODO commented area in PostsFragment?
|
Mark M. |
View paste
|
Aaron |
yes, but more broadly, I just suspect the overall way in which I am applying the strikethrough formatting is too convoluted
|
Oct 11 | 7:55 PM |
Aaron |
I think that call to notifyDataSetChanged is probably the worst part of it, but I think it's probalby not the only issue
|
Mark M. |
IMHO, your problem lies elsewhere, but you are seeing the pain here
|
Aaron |
very possible
|
Aaron |
that is actually the kind of answer I am looking for, so please feel free to elaborate
|
Mark M. |
hang on
|
Aaron |
np
|
Mark M. |
you have divided your repository along data source lines
|
Mark M. |
well, no, actually that's not really true: you just have NoSurfRepository, right?
|
Aaron |
yes, I just have that repository, and the only state that I really keep are the IDs of clicked posts. I don't store or cache any of the content from Reddit
|
Mark M. |
right
|
Mark M. |
I would argue that it is the repository's job to stitch together the data from the disparate data sources
|
Mark M. |
your fragment and adapter should be getting an idealized object model, with the data needed, in a structure that makes it easy to render that data
|
Oct 11 | 8:00 PM |
Mark M. |
all the hard stuff goes in the repository
|
Mark M. |
so, when you ask the repository to give you posts, the post objects that it supplies should have a field that indicates whether they were read or not
|
Aaron |
that makes sense
|
Mark M. |
your PostsAdapter should wind up be *much* simpler
|
Mark M. |
er, being much simpler
|
Mark M. |
in the repository, you will still have two separate reactive sources: Retrofit and Room
|
Aaron |
yes that makes a lot of sense
|
Aaron |
great, OK
|
Mark M. |
that's where your RxJava idea comes into play
|
Mark M. |
as RxJava provides a much richer "library" of ways to assemble multiple reactive sources into a single outbound stream
|
Mark M. |
LiveData, by contrast, offers nothing in that area
|
Mark M. |
this is why I expect that most developers will use RxJava in their repository, converting them to LiveData for UI use, so the reactive results become lifecycle-aware
|
Aaron |
yes, I am trying to think through how I might do it, but I am having a little trouble thinking it through in a concrete enough way without actually working with code
|
Aaron |
any suggestions about how I can approach it without RxJava for now? I mean, I guess I could take this opportunity to start learning it
|
Aaron |
but I am trying to proceed incrementally with learning and upgrading how I am doing different things
|
Oct 11 | 8:05 PM |
Mark M. |
sorry, this is slow, as I don't know your code that well
|
Mark M. |
so, you are using traditional callbacks with Retrofit, and using those to populate a MutableLiveData, right?
|
Aaron |
correct
|
Aaron |
technically there are 2 similar MutableLiveDatas
|
Mark M. |
when you call methods like requestAllSubredditsListing() on your repository, are those calls being made on the main application thread?
|
Mark M. |
(with you relying on Retrofit for handling the background thread?)
|
Aaron |
yes
|
Mark M. |
OK
|
Mark M. |
first, I think there is a LiveData adapter for Retrofit, if you wanted to get rid of the callback + MutableLiveData part
|
Aaron |
ok, interesting
|
Mark M. |
basically, instead of your RetrofitInterface having methods that return Call<Whatever>, they would return LiveData<Whatever>
|
Aaron |
right
|
Mark M. |
you register it similarly to how you register your Gson adapter
|
Mark M. |
there is definitely an RxJava adapter for Retrofit, and I'm reasonably certain somebody has created a LiveData one
|
Oct 11 | 8:10 PM |
Mark M. |
regardless, one way or another, you have a LiveData of Retrofit results, and a LiveData of Room results
|
Aaron |
yes
|
Mark M. |
what you want is to stitch those together and have a LiveData of the combined results, with posts knowing whether they have been read or not
|
Mark M. |
IIRC, we talked about MediatorLiveData in a recent chat
|
Aaron |
yeah
|
Mark M. |
and I said that one place where that gets used is in transformations
|
Mark M. |
Transformations.map() and Transformations.switchMap() both use a MediatorLiveData (again, IIRC)
|
Mark M. |
and in "Android's Architecture Components", I show how to write a filter() transformation much the same way
|
Aaron |
(yes, I remember, and I actually implemented some Transformations in my ViewModel to create a viewstate as you mentioned, which helped me move a lot of logic out of my fragments)
|
Aaron |
ok, I've skimmed the piece about the filter, yes
|
Mark M. |
yeah, I thought I saw something like that when I skimmed your code
|
Mark M. |
your stitch-the-data-together situation is basically another place for a transformation
|
Mark M. |
the function takes in the two LiveData objects and returns a LiveData representing the combined result
|
Mark M. |
in RxJava, this transformation function is called zip()
|
Mark M. |
you could create your own LiveData zip() equivalent
|
Aaron |
ok, cool, that gives me a great starting point
|
Mark M. |
it might be a bit tricky, but at the same time, somebody might have written up how to do it, given that it is a standard RxJava "operator" that somebody might have applied to LiveData
|
Oct 11 | 8:15 PM |
Mark M. |
BTW, here is the Retrofit LiveData adapter: https://github.com/leonardoxh/livedata-call-ada...
|
Aaron |
are you saying that the filter() transofmration shares some similarities with what you are suggesting re: zip(), or are you just mentioning filter() insofar as it's an example of a custom transformation more generally?
|
Mark M. |
it's an example of a custom transformation
|
Aaron |
ok
|
Mark M. |
this GitHub issue points to a couple of gists with zip() implementations for LiveData, though I think they are in Kotlin
|
Mark M. | |
Aaron |
ok, cool, and thanks for the links
|
Aaron |
by all means, post anything else if you are typing it, but let me also ask my second question before time runs out
|
Mark M. |
go right ahead!
|
Aaron |
for this one I need some advice about where/how to debug
|
Aaron |
I am using the AppCompat night mode
|
Aaron |
as an option in my settings
|
Aaron |
it seems to work fine and as expected except for one case
|
Aaron |
when I go BACK from a WebView and return to PostsFragment, some of the text and other resources are wrong. take a look at this screenshot
|
Aaron | |
Aaron |
as you can see, the text and refresh button are the wrong color
|
Oct 11 | 8:20 PM |
Aaron |
I am not sure why this is happening and TBH I am not sure how to start figuring it out
|
Aaron |
any suggestions?
|
Mark M. |
well, I haven't looked at all at AppCompat's night mode support
|
Mark M. |
what is the basic implementation: separate themes?
|
Mark M. |
IOW, how are you telling AppCompat what you want in night mode versus, um, non-night mode?
|
Aaron |
versioned resources with a -night suffix
|
Aaron |
which seem to work fine in general... except after a WebView is displayed
|
Mark M. |
OK, that's standard night mode
|
Mark M. |
if I had to guess, it's a bug somewhere in AppCompat
|
Mark M. |
see if you can reproduce it in a simple project
|
Mark M. |
and then see if you can reproduce it when using the latest-and-greatest appcompat version (if you're not on the latest already)
|
Aaron |
that is what I was afraid of. if that turns out to be the case, what is a good alternative way to implement night mode?
|
Mark M. |
if you can reproduce the problem, consider filing a bug report with the sample project
|
Mark M. |
um, frankly, there isn't a good alternative way to implement night mode
|
Mark M. |
there are two possibilities that I see:
|
Mark M. |
1. AppCompat knows that it should be in night mode but is misapplying the resources somehow
|
Mark M. |
2. AppCompat does not know that it should be in night mode
|
Mark M. |
-night resources, though, are a system thing, not an AppCompat thing
|
Oct 11 | 8:25 PM |
Aaron |
I see
|
Mark M. |
which means unless Google did something really strange, option #2 should not be possible
|
Mark M. |
I cannot rule out Google doing something really strange
|
Mark M. |
they do that on days whose names end in "y"
|
Aaron |
=>
|
Mark M. |
BTW, how are you testing this? hardware or an emulator?
|
Aaron |
both
|
Aaron |
same problem on both
|
Mark M. |
OK, that eliminates environment as a source of problems
|
Aaron |
I think I just need to do some heavy duty reading about themes/resources
|
Mark M. |
my limited night mode experience means that I don't really have great answers for you
|
Mark M. |
possibly, though I doubt it
|
Mark M. |
insofar as problems there should be consistent
|
Mark M. |
IOW, they would be broken all of the time, not just on specific forms of navigation
|
Mark M. |
I assume that this is going from PostsFragment to some display fragment with a WebView?
|
Aaron |
NoSurfWebViewFragment
|
Mark M. |
so, from PostsFragment to NoSurfWebViewFragment?
|
Aaron |
sorry, PostsFragment->PostFragment->NoSurfWebViewFragment
|
Oct 11 | 8:30 PM |
Aaron |
list of reddit posts -> one reddit post -> external link associated with that post
|
Mark M. |
those screenshots look like they would be from PostsFragment (lists), not PostFragment
|
Aaron |
sorry, yes, they are. what I mean is ,the navigation flow works as above ^
|
Aaron |
but yes, the problem happens in PostsFragment, after BACK is pressed on PostFragment
|
Mark M. |
is PostFragment also exhibiting the problem?
|
Aaron |
no
|
Mark M. |
does your overflow menu in PostsFragment lead to other fragments?
|
Aaron |
I do not want to keep you past the normal time; I appreciate your help but I can poke around more and return later
|
Aaron |
um, yes, I think so
|
Aaron |
yes
|
Mark M. |
see if navigation through those paths exhibit the same probelm
|
Mark M. |
er, problem
|
Aaron |
what would that indicate?
|
Mark M. |
basically, you're assuming that the WebView is part of the problem, which may be the case, or it may not
|
Aaron |
ok I got you
|
Aaron |
I will try that line of investigation
|
Aaron |
thanks a lot!
|
Mark M. |
another test would be to temporarily wire PostFragment to not launch NoSurfWebViewFragment, but instead show something else (e.g., settings)
|
Mark M. |
and see if the problem occurs that way
|
Aaron |
ok, I will see if I can rule WebView in or out as being part of the problem
|
Mark M. |
your WebView-is-the-culprit theory may be true, but it's worth considering alternatives
|
Mark M. |
right
|
Aaron |
agreed
|
Mark M. |
regardless, if you do come up with a reproducible scenario and file a bug report, support libraries are relatively decent about getting bug fixes
|
Oct 11 | 8:35 PM |
Mark M. |
so, the "how do I get night mode working?" might be a matter of just waiting for a bug fix
|
Mark M. |
and with that, let's call it a wrap for today
|
Aaron |
ok, much appreciated
|
Aaron |
talk later
|
Mark M. |
next chat is Saturday at 4pm US Eastern
|
Mark M. |
have a pleasant evening!
|
Aaron |
sounds good, you too
|
Aaron | has left the room |
Mark M. | turned off guest access |