Office Hours — Today, July 30

Tuesday, July 28

Jul 30
7:20 PM
Mark M.
has entered the room
Mark M.
turned on guest access
sudokai
has entered the room
sudokai
Hi Mark
Mark M.
hello, sudokai!
how can I help you today?
7:25 PM
sudokai
Hi Mark, we are interviewing an Android candidate to join our team.
What kind of questions would you ask?
Eager to hear your thoughts, given your experience.
Mark M.
um
my interviewing style is probably unusual, in part because it is old
sudokai
Let's hear it :P
Mark M.
I recently have had to help on some interviews, but prior to that, it had been 20 years since I was involved in hiring anyone
so, I claim no particular expertise in the art of modern interviewing
what level of candidate is this? junior? mid-level? senior?
sudokai
But you have a lot of Android experience
Mid-level I'd say
7:30 PM
Mark M.
View paste
I have five bullet points that I use for questions, and based on their answers I usually follow up with related questions along the way:

- Played with coroutines? RxJava?
- Thoughts on Android 11?
- PR reviews: what do you look to receive? what do you look to give?
- JIRA experience?
- Remote development experience, pre-pandemic? Thoughts on remote?
this assumes that I have reviewed a resume/CV/LinkedIn profile, though I usually have questions based on what I see there
my objective in an interview is mostly as a "BS detector" and to get a sense for how well they communicate
the "BS detector" is to ensure that they really do have the background that they claim
sudokai
They have to have worked with Kotlin, RxJava, ExoPlayer, Dagger, MVVM
Yeah, I see it the same way
As a "BS detector" I mean
Mark M.
right, so I'd be asking them to describe their experiences with those things, and asking follow-up questions based on their answers
I'm not a big "write some code for me" type of interviewer, in part because I wouldn't have the time for that and questions, and in part because we simply never do that sort of thing (write random code under pressure with an audience)
sudokai
Yeah, I was surprised how hard FizzBuzz seemed for some people
Tad F.
has entered the room
Tad F.
Hi Mark
7:35 PM
Mark M.
hello, Tad!
sudokai: let me take a question from Tad, and I will swing back to you in a bit
Tad: how can I help you today?
sudokai
Sure
Tad F.
I have a question about Preferences.
I haven't migrated to the jet pack approach yet
In the classic approach, I am using preference headers: "General", "Sync", and something called "Media Site Access"
Under the latter I have quite a few types of sites where the user can enter their credentials to allow the app to let them get at their media
Dropbox, Instagram, FB, etc
I really don't want one big preference screen for this
What I want is something like "sub-headers"
But I haven't been able to find anything
The fragments for each to gather credential info are quite different
Mark M.
are you sure that you really want that to be in a PreferenceFragment, then?
Tad F.
They have different callbacks, some actually have to start a separate auth token process, so I capture on onResume call to keep going, etc.
Mark M.
(or rather in a fragment showing a preference-style UI)
Tad F.
Well, I was trying to capture a consistent "preference" UI experience across all these settings...
do you have an alternative suggestion?
Mark M.
I was going by "the fragments for each to gather credential info are quite different", which seems to imply that your consistent UI objective would be difficult
Tad F.
I think if I could get something like a "sub-header" that would appear when the user chose "media site access", then the individual items on that sub-header screen could each be assigned their separate preference fragment that would work ok
I meant that what the individual behavior is for each media set set of preferences actually do to gather the credentials is different
7:40 PM
Mark M.
I haven't had to do this in years and years, but AFAIK the AndroidX preference system still allows you to have a <Preference> that either ties to an Intent or is just one that you attach a listener to at runtime
Tad F.
For example - Dropbox requires that you essentially start another activity - it accesses dropbox, then when it returns in onResume you can check for the status of the auth token
Instagram is not like that at all
Mark M.
yeah, I wouldn't have this in a preference screen
Tad F.
Where would you have it?
Mark M.
I'd use the preferences for other stuff and have an account manager fragment for presenting the list of accounts and how to add/edit/remove them
whether that account manager fragment is linked to from the preference screen is up to you, though I'd probably give it more visibility than that
but, regardless, a plain Preference should allow you to link to whatever you want
Tad F.
So right now my drawer menu off the main activity has a "Settings" choice that launches the preference activity. You are suggesting I have a separate entry there for 'Account management' separate and distinct from the launch point for "Settings"?
Mark M.
my gut says that yes, that's how I would do it
Tad F.
Interesting...I'll think about that.
Mark M.
it feels like accounts are a Really Big Deal for your app
and I worry that not everyone bothers looking at "settings"
Tad F.
They are important yes - they allow the user to choose media from their favorite social media sites for inclusion in the playlists my app builds
From within the SAF
(I'm writing documentsproviders for those sites that don't already have them)
Mark M.
you probably then want to make it easy for them to set up a first account and easy for them to add new ones
Tad F.
One other question - I seem to recall somewhere along the line that Ringtone Preference has been deprecated, or is not supported or some such in the new preference world, is that right
Mark M.
unless you are doing a custom onboarding experience, both of those are probably simpler if they are not blended in with other preferences
Tad F.
?
Mark M.
correct, they never ported it to the AndroidX preference system
7:45 PM
Tad F.
Currently I'm allowing the user to select a ringtone for notification(s) of various sorts.
Mark M.
you can create your own ListPreference for that populated at runtime
Tad F.
Yeah, ok.
Just more work ;)
Mark M.
it's just that they didn't want the preference library to have a bunch of code related to looking up ringtones, as I recall
Tad F.
RingtoneManager is still in place then, I take it
Mark M.
I think so, but I haven't worked with it in ages
let me take another question from sudokai, and I'll be back with you in a bit
Tad F.
Sure
Mark M.
sudokai: over to you! do you have another question?
sudokai
Mmmm, still thinking about interview questions
Go ahead guys
Tad F.
Mark - I've been reading some about the deprecation of AsyncTask, and am wondering if you can point me to examples of best practice replacements?
Mark M.
sudokai: OK -- ping me if you're ready for another round!
Tad F.
I saw an interesting post by EpicPandaForce on SO fairly recently...any input?
Mark M.
um
Tad F.
I am using it now for short lived tasks, always extending in a static class, always using weakref, etc.
Mark M.
in terms of AsyncTask replacements, the best replacement is "rearchitect your app and getting that code the heck out of your UI layer"
sudokai
I use WorkManager
Mark M.
AsyncTask only ever really made sense if you were doing long-running work directly in an activity or fragment
and in modern architectures, that's a no-no
sudokai
now you can execute immediate work with the foreground service mode and there's no 10 minute restriction
7:50 PM
Mark M.
WorkManager has its benefits for "bigger than a breadbox" sorts of things, but I tend not to think of it as a replacement for AsyncTask
Tad F.
Really? The docs specifically mention it isn't for long running tasks...I've actually never used it that way because I was worried that even using a threadpoolexecutor the queue would fill up
Mark M.
for transactional sorts of work (Web service calls, database I/O, etc.), the typical approach nowadays is a reactive framework: Kotlin coroutines, RxJava, etc.
Tad F.
when you say "getting that code the heck out of your UI layer", what is "that code"? threading?
Mark M.
more or less, yes
saying that you use Glide or Picasso for image loading directly in the UI layer is fine
Tad F.
Wait - so you are advocating for no threading in the UI layer?
Mark M.
correct
the recommended architecture pattern is that stuff moves into repositories and data sources
they handle the I/O and the threading needed for that I/O and deliver results reactively
Tad F.
What I'm using it for is to gather various bits needed when a user chooses a media item from a resource where it is going to take some time to download, process, etc.
sudokai
I use RxJava
Tad F.
So Glide oriented (and in some cases I partially use Glide)
Mark M.
for album art, that's reasonable
Tad F.
I also use it to validate login to the website
Mark M.
some things, like OAuth, are unavoidably tied to the UI layer
Tad F.
Throw up an indeterminate progress bar, do the validation in the thread, and return yes/no
validate login to the app by hitting the website, I should say
Mark M.
and for that, RxJava or coroutines would be the replacement for AsyncTask
7:55 PM
Mark M.
and in your case, a lot of your "heavy lifting" presumably is in your DocumentsProvider implementations
Tad F.
Yes - there is a thread in there that fetches doc info in batches
Which actually brings me to my last question, unless sudokai you are ready to jump in?
Mark M.
Tad: I think you can go ahead
Tad F.
I'll give an example about the documentsprovider I just did for Instagram
In that case, their API allows you to specify a "limit" in the call for doc info, let's say it is 10
So they return 10 items, and they also return a "paging" bit of json that lets you know a url for the "previous" page and "next" page
Mark M.
that's a reasonably common REST pattern
Tad F.
But i haven't been able to translate this into any API on the DocumentsProvider side
I am looking for a way to signal to the provider framework that I'm not done, but I need it to jog me when the user "pages down" past the current end to see if there is any more.
Not finding anything
8:00 PM
Mark M.
I doubt that there is such a thing
Tad F.
You can signal the framework to keep pinging you to get more entries, and then signal it to stop doing that.
But that's it.
Mark M.
DocumentsContract was not set up with paging in mind
Tad F.
So my thread currently would just keep spinning until Instagram didn't include a "next" paging
Which if you have 1000's of photos is gonna be a problem
So what is the recommended way to utilize SAF and hit a site that has 1000's of entries?
hit a resource, I guess I should say
Mark M.
well, please understand that I would not be at all surprised if you are one of fewer than 100 developers worldwide who is trying to do this sort of thing
the DocumentsContract model is more of local filesystems, SMB/CIFS, and simple document stores (your Google Drives and Dropboxes of the world)
Tad F.
Even if we used it on the local device, it is possible for there to be tons of files, no?
Mark M.
sure, but they are usually organized into directories
and the DocumentsContract model adopts that tree approach
if the user is silly enough to have tons of files in a single directory, and the I/O is a bit sluggish, that's really their own problem
Tad F.
Dropbox certainly acts that way
But Instagram, Flickr, pintrest, FB, etc. don't
Mark M.
my best guess is that you might need to keep a local cache of the metadata that you synchronize periodically
but that's just a guess
again, I doubt your desired use cases were what the DocumentsContract people had in mind
Tad F.
Local disk cache, I guess you are meaning. I have a cache now that the thread feeds into, but it is memory based
8:05 PM
Mark M.
yes, I was assuming a persistent cache, that would survive between uses of your provider (whether used by your app or other apps)
Tad F.
Even with a disk based cache, what you populate is rows in a cursor - so it ends up going into memory anyway
Mark M.
I assumed that the concern was avoiding network I/O for calls that would require multiple pages from the SDK
so, the network-based SDK would be feeding the cache, and the cache would be what your DocumentsProvider API works off of
Tad F.
No - the concern is the model now just grabs all files that are available, and for resources that aren't "directory" focused, I am concerned about overloading the memory consumption of the app.
Mark M.
ah
I think the "all files that are available" may need to be revisited :-)
Tad F.
Yeah - hence my original question about any way to have the DP framework support a paging model
Mark M.
no, I was thinking more in terms of virtual directories
even for some service that is more based on tags or something, you can set up virtual directories based on a tag, to limit the number of items you have to deal with at a time
or virtual directories based on date
or virtual directories based on other metadata
8:10 PM
Tad F.
I was just thinking along those same lines - but the tricky part will be back in the UI knowing when the set of entries I've passed back is really at the "end", so I could enable/disable a "next set" button or something.
I don't control the chooser UI
Mark M.
and you wouldn't need to, as there is no "next set" button
the UI displays everything in a directory
you need to set up your tree such that a directory is reasonably-sized for both you and the user
Tad F.
Yes, that's right
I'll have to come up with a scheme in the provider to create faux directories I guess
Mark M.
that's my guess
Tad F.
Ugh.
OK
Mark M.
IOW, figure out a tree structure for the data, and use that to drive your directories
Tad F.
Well, most of those providers just give you a flat list of however many media items the user has uploaded.
So I'll just pick some number - say "every 100" and create a new directory internal to the provider
Mark M.
will the user be able to make sense of that?
Tad F.
Well, I'll have to come up with something more creative than "first 100", "second 100", :)
Mark M.
I was assuming that there was some metadata about the items (tag, dates, etc.) that would make logical divisions for you and the user
Tad F.
Not sure what other choice I haev
Not consistently
Maybe date
Mark M.
rolling back a bit in the advice, your on-disk cache would be of the relevant metadata options
it doesn't need to be consistent across providers
it only needs to be consistent within a provder
Tad F.
I'm doing a year/month/week recyclerview already in the app for media they have included in their playlists.
Mark M.
er, provider
Tad F.
So I could present the provider the same way
8:15 PM
Mark M.
that's a possibility
Tad F.
Sudokai - any questions from you?
I actually have one more, but will wait
It's gonna be tricky to do that date thing, because many don't deliver them to me by date order.
But I'll look into something like that
Back to RxJava - I haven't used this yet. It is an entire "way of doing things"? i.e. is this a platform I'll need to learn?
Mark M.
um, kinda
I mean, it's not an OS
but reactive programming in general is a bit of a philsophy
and RxJava has a particular implementation of that philosophy
Tad F.
I've heard about it - just haven't used it. I've done a lot of threading in Java over the years, written my own thread pools, yada yada. I've also done some stuff with Promises in Node js
Mark M.
RxJava is basically a set of thread pools (schedulers) with a managed callback system (subscribers)
Tad F.
Do you discuss it in any of your books?
Mark M.
I have a chapter on the basics of RxJava in *The Busy Coder's Guide to Android Development*
Tad F.
ok I'll check it out.
As always, thanks for your input!
Mark M.
it's a bit thin, insofar as there are whole books just on RxJava
Tad F.
Bye
Mark M.
see you later!
Tad F.
has left the room
8:20 PM
Mark M.
sudokai: if you have any other questions, go right ahead! I assumed that you didn't have any, since you were not chiming in
sudokai
Yeah I was looking at top questions on Stackoverflow
:D
Are any advantages of coroutines over RxJava?
8:25 PM
Mark M.
IMHO, they are substantially easier to learn
and they are a bit more natural to read
for example, in most cases, normal try/catch for exception handling "just works"
sudokai
Any performance advantages?
Mark M.
I haven't seen a performance comparison
sudokai
Well, I find the coroutine scope stuff utterly confusing
it's nice if you don't need to care: viewModelScope
Mark M.
agreed
for sophisticated stuff, if you are having to create your own scopes... yeah, it's confusing
sudokai
Anyway, thanks for the advice
Mark M.
for a lot of developers, stock Jetpack scopes handle most of the cases
sudokai
I still haven't looked into Dagger Hilt
There's a lot of hype
but I use Koin
Mark M.
I've glanced at it, nothing more
sudokai
The only problem with Koin is that it's not typesafe
Mark M.
I'm a Koin fan as well, though I expect that I will use Hilt in *Elements of Android Jetpack* for a Java DI example
sudokai
Dagger seems super hard
I remember Spring for web. That's easy and beautiful.
Dagger has always seemed monstruous to me
Mark M.
Dagger is aggravating to get set up, and so the hope is that Hilt will make that a bit better
and once you have enough Dagger set up, a lot of the ongoing stuff is copying boilerplate
sudokai
These days I try to stay away from the hype
:)
8:30 PM
Mark M.
I try to minimize worrying about pre-release Jetpack libraries
sudokai
When I see something new, I ask myself: does this help me build better apps?
Mark M.
I have a rough enough time dealing with pre-release OS versions and IDEs
sudokai
Like things I couldn't do before
Or does it simplify my code by an order of magnitude?
Mark M.
(and, admittedly, I am working with a pre-pre-pre-release Jetpack Compose, just 'cause it's gonna be huge)
sudokai
Have you looked at Flutter?
Mark M.
briefly
sudokai
I know it's Flash for mobile phones, but it's looking promising
It's so easy to create interfaces that are pixel perfect for both platforms
I haven't looked at Jetpack Compose yet
I'm subbed to your newsletter though
I'm still going through the motions of catching up
Many years of Android stuff to go through
I know Jake Wharton is super against Flutter and technically right
Mark M.
Compose will be huge, but unless you really want to kick the tires on it, there's no reason to pay attention to it until a 2021 beta, or at least a couple-months-from-now alpha
sudokai
But people don't care
The little I saw of Compose, I liked
Mark M.
I was just worried about Flutter being too tied to Fuchsia early on
nowadays, Flutter has enough momentum that it might survive even if Google pulled the plug
sudokai
My point is that people like Jake say Flutter should die in hell, but users don't care
8:35 PM
Mark M.
I generally agree
sudokai
Users don't care if you use MVVM, OOP, whatever
Mark M.
I worry a pinch about the iOS platform fidelity, as it's not like Apple is "on board" with Flutter
but, for a lot of users, platform fidelity doesn't really mean a ton
sudokai
Flutter is superior to React Native because it renders everything it's flash
With React Native, you always get weird quirks
Mark M.
to an extent, Compose is Flutter for Kotlin, insofar as they both take the same approach (direct Skia canvas rendering)
sudokai
Like you use CSS to specify box shadow for iOS, but on Android you need to use elevation
Yeah, that's the part I liked
Mark M.
but, alas, I need to continue on with the rest of my evening
sudokai
This thing of mixing XML and Java and the names are different, oh there's a bug unfixed for 5 years, etc.
Have a good evening!
Mark M.
you too! the next chat is Thursday, 4pm US Eastern!
sudokai
has left the room
Mark M.
turned off guest access

Tuesday, July 28

 

Office Hours

People in this transcript

  • Mark Murphy
  • sudokai
  • Tad Frysinger