Office Hours — Today, April 10

Thursday, April 8

Apr 10
3:50 PM
Mark M.
has entered the room
Mark M.
turned on guest access
4:00 PM
Scott W.
has entered the room
Mark M.
hello, Scott!
how can I help you today?
Scott W.
hello
I've got 3 topics to ask about
1. I'm trying to implement a text view widget that can be read aloud and will highlight the word that's being read.
I've got TextToSpeech working to read the contents of a TextView
but I'm not sure how to accomplish highlighting the word as it is read.
Mark M.
is your concern "how do I highlight words?" or "how do I found out what is being read?"
Scott W.
both. My bigger concern is how to know which word is being read though.
Mark M.
unfortunately, that is the one that I cannot help with, as I have zero experience with text-to-speech
Scott W.
shoot
4:05 PM
Mark M.
that answer shows the "how do I highlight words?" part
in a nutshell, you set and clear spans on a SpannableString
that example uses BackgroundColorSpan, but there are other subclasses of CharacterStyle if you are looking for a different effect
Scott W.
ok so I would have to make repeated calls to setText() giving it the new SpannableString with the updated highlighted word?
Mark M.
that would work
trocchietto_Ivano
has entered the room
Mark M.
it's not out of the question that you could set and clear spans on a SpannableString that you created earlier and put in the TextView, then ask the TextView to redraw
that might be a touch more efficient
I was focusing on the basics (and the accompanying material in *The Busy Coder's Guide to Android Development*), not with an eye toward optimization
(BTW, hello, Ivano! I will be with you shortly!)
trocchietto_Ivano
okido
Scott W.
I'm not concerned with efficiency yet, but if it's just as easy to do that way then I'll go for it.
4:10 PM
Scott W.
all right I'll save number 2 for when there's a moment after you an Ivano chat
Mark M.
sounds good!
Ivano: how can I help you today?
trocchietto_Ivano
cool i have bullet questions
first one is : why there is an 'inline` in public inline fun <T> Collection<T>.isNotEmpty(): Boolean =!isEmpty()
Mark M.
efficiency, most likely
trocchietto_Ivano
I do not see any lambda that juastify the inline optimization
Mark M.
on the other hand, the implementation is just a ! applied to another call
trocchietto_Ivano
justifies*
true
Mark M.
for some of the standard Kotlin library, they will be a bit more aggressive about using inline, particularly for functions that they expect will be used a lot
they have to consider the entire Kotlin ecosystem -- you just have to worry about your app
trocchietto_Ivano
ok thanks touchbased I pass to scott so to prepare the second question
Mark M.
um, OK
Scott: back to you!
Scott W.
2. I need a simple touch to draw widget and a way to save the data of the picture.
I've implemented a drawing system using a third party library before, and it takes a lot of work to make it look ok.
4:15 PM
Scott W.
Do you know of a best way to accomplish the drawing part of this task?
or a way that uses standard libraries?
Mark M.
well, I would use one of those third-party libraries, such as perhaps https://github.com/PicnicSupermarket/FingerPain...
I don't know how you are defining "standard libraries" in this context
if you mean "something from Google", I am not aware that they have published such a thing -- it's definitely not in the framework or Jetpack
Scott W.
this is what I mean.
do you have any experience with the PicnicSupermarket library you linked?
Mark M.
nope -- it was the first thing that showed up in my Android Arsenal search
Scott W.
ok. That's the end of question 2
Mark M.
if you're really more after collecting a signature, see https://android-arsenal.com/tag/171 for a few
OK, I'll be back with you in a bit
Ivano: over to you!
trocchietto_Ivano
OK thanks I saw an interesting tutorial regarding Room where the author claim that the instance od the db should be made vola
volatile
in this way
View paste (6 more lines)
abstract class ShoppingDatabase: RoomDatabase() {

    abstract fun getShoppingDao(): ShoppingDao

    companion object {
        @Volatile
        private var instance: ShoppingDatabase? = null
        private val LOCK = Any()

        operator fun invoke(context: Context) = instance
            ?: synchronized(LOCK) {
            instance
                ?: createDatabase(
                    context
                ).also { instance = it }
...
is this a good practice?
Mark M.
well, personally, I would have it be created and injected by a dependency inversion framework, such as Dagger/Hilt or Koin
trocchietto_Ivano
and the framework takes care
ok
thanks
4:20 PM
Mark M.
if you need to do this sort of thing yourself, @Volatile might be needed -- I forget the rules off of the top of my head
trocchietto_Ivano
OK
Mark M.
OK... Scott: what's your third question?
trocchietto_Ivano
ok thanks in your from rxjava to coroutine MainMotor example that fetch the weather with a new stack, I am wondering if would have been possible to initialize also the Adapter with a
sorry
did not want to press enter was preparing the question
I apologize
Mark M.
no problem!
trocchietto_Ivano
:)
Scott W.
I've been interrupted. I'll be back in a few minutes
Mark M.
OK
Ivano: if you want to try again for that next question, go ahead!
trocchietto_Ivano
ok
View paste
ok thanks in your from rxjava to coroutine MainMotor example that fetch the weather with a new stack, I am wondering if would have been possible to initialize also the Adapter with a
 Single as
4:25 PM
Mark M.
if you are asking "can we use RxJava in the UI layer?", the answer is yes, if you are careful about your lifecycles
trocchietto_Ivano
no
Mark M.
OK, then, I am afraid that I do not understand your question
trocchietto_Ivano
my question is can i use koin to initialize with DI an adapter with the Single
I tried but did not work
Mark M.
is it technically possible? perhaps
but it does not sound promising, with respect to things like configuration changes
trocchietto_Ivano
i am afraid I do not get, you mean is not future proof?
Mark M.
no, I mean if you rotate your screen, you might have problems
trocchietto_Ivano
ah
I see
thanks
Mark M.
and Koin is really designed more for making major objects available to other major objects -- having Koin try making a call to a repository and passing a result to an activity/fragment is not really what Koin is for
trocchietto_Ivano
because the adapter is not managed in the viewmodel
so I should use dagger?
Mark M.
Dagger is complex
Dagger with Hilt is supposed to be not that bad, but I have not tried it yet
trocchietto_Ivano
i saw in fact in the clean architecture repository from joe bich that he uses dagger for the adapter
Mark M.
Dagger is preferred for larger projects, particularly with larger teams
trocchietto_Ivano
OK thanks as always you give me good research hints
thanks
Mark M.
sure!
Scott: are you now de-interrupted? :-)
trocchietto_Ivano
lol
4:30 PM
Scott W.
yes
My question is about fragments and possibly inheritance
my app has 8 similar fragments. This is a single activity application
lots of the fragments are split into 3 sections vertically with the top and bottom being the same, but the middle is different
the fragment navigation is being managed by the navigation xml
Is it ok to have an abstract parent class that deals with the top and bottom sections and then the concrete classes manage the middle section of these fragments?
Mark M.
that could work
Scott W.
My concern is that there is a more "fragment" way of doing this. I'm not used to using fragments in this way.
Mark M.
not really -- in the end, fragments are just classes, so you use composition and inheritance as makes sense for your needs
4:35 PM
Scott W.
ok
Mark M.
so, for example, the abstract parent class could know intrinsically how to manage the top and bottom sections, or it could delegate those details to something else, such as nested fragments
if all 8 subclasses have near-identical top and bottom sections, and you do not anticipate any changes to that any time soon, just having the abstract parent class handle those is reasonable
Scott W.
nested fragments means the view is made up 3 separate fragment potentially?
Mark M.
you could have a fragment that holds three fragments
Scott W.
I see
ok I have more question that I would like to ask after Ivano gets his turn
Mark M.
Ivano: do you have another question?
trocchietto_Ivano
thanks Mark my next bullet pill is about DI. I used to click for instance a ViewModel class name pointing the cursor and pressing ctrl B (I remember you use ubuntu) and I could see the activity that was calling the viewModel, this is really useful to see the flow of an app without using debugger or logs. Now with dependecy injection as Koin if I do ctrl B to see who calls a class I go to the Application Koin class and do not get any reference to the Activity. As workaround I try to search for public properties(instance variables) or methods where I use ctrl B, but this is quite time consuming. How can I know which activity istantiate a VM if I use a dependecy injection framework?
Mark M.
um, Ctrl-B is still useful for me -- you just look for the result in a different section of the "Find" pane
trocchietto_Ivano
ah
thanks
4:40 PM
Mark M.
actually, find is Ctrl-F7, which I tend to use more
trocchietto_Ivano
Cool
Mark M.
but, for example, I just did Ctrl-B on the definition of a ViewModel that is being injected via Koin, and the fragments that reference it showed up in the pop-up window
trocchietto_Ivano
hollly jolly I did not think about that
good one, better than search for my habits
thanks
Mark M.
Koin (and Dagger/Hilt and other forms of DI) add some indirection, but I have not had problems navigating the project source as a result
trocchietto_Ivano
loving intelliJ
so I will do
Mark M.
yes, having a decent IDE can help
Scott: back to you! do you have another question?
Scott W.
yeah I've got a few simple kotlin questions.
In a Kotlin file, there can be constants defined above the class declaration
but then constants are also defined in the companion object
4:45 PM
Scott W.
where should something like LOG_TAG go? When do you use one place over the other?
Mark M.
my personal approach is: if the value is only needed locally, define a private top-level constant
if the value is needed as part of an API, put it as a constant in a companion object, for namespacing
so, in your case, it really depends on who all needs that LOG_TAG: is it just the class(es) in the current file, or is it the whole module?
Scott W.
how is a top-level constant referenced in Java?
Mark M.
IIRC, it would be based on the Kotlin file name
so, if you have Foo.kt that has LOG_TAG in it, I think it turns into FooKt.LOG_TAG in Java
but I do very little Java interop nowadays, so I may be mis-remembering
(i.e., I'd have to look it up in my own book)
Scott W.
got it
next kotlin question is... should views I want to hold onto as member variables be defined with the lateinit keyword?
lateinit seems like a bad thing to do for some reason.
like it's anti-kotlin
Mark M.
um, well, that depends completely on when you are going to do the init :-)
in a custom view, you might not need lateinit, as you might be initializing them in the constructor
Scott W.
in a fragment I am doing the init in onCreateView
Mark M.
in an activity or fragment, you would need to use lateinit
assuming that you are not using view binding, data binding, Kotlin synthetic accessors, etc.
Scott W.
nah I haven't gotten into any of that yet
4:50 PM
Scott W.
all right that's all for me today. Thanks for the help!
Mark M.
you're welcome!
Ivano: back to you! do you have another question?
Scott W.
bye bye now
trocchietto_Ivano
Thanks Mark, regarding the Scott questions I am finding really useful the klassbooks on your site the this is a shameful question. Actually I have a poor understanding of the Retrofit Endpoints. I saw on your project that the interface is returning an object `ObservationResponse` and so in other repositories I am studying, but should not be COMPULSORY to return the retrofit RESPONSE, where you get back the error or the onSuccess? Am I missing some basic building block in my old neurons?
bye bye Scott and have a look at klassbook from Mark are really cool if you did not do
Scott W.
will do. thanks
trocchietto_Ivano
bye
Mark M.
Ivano: if you do not return the Response, Retrofit converts errors into exceptions and throws them
trocchietto_Ivano
yes and is that not compulsory to do it?
furthermore we often modelize responses with sealed class that have success, loading and error
Mark M.
well, it is your choice of how to consume the results: use the Response or catch the exceptions
trocchietto_Ivano
ah I see
that is why you use try catches in the activity!!!
checkmate
Mark M.
there are other approaches, such as EitherNet: https://github.com/slackhq/EitherNet
basically, it tries to strike a middle ground between raw Response objects and the exceptions
it gives you a standard sealed class and standard conversions of response codes to Failure types
I have not used this yet, though I am considering experimenting with it
trocchietto_Ivano
i will try to do it thanks by the way there is a plugin fantastic that convert json responses in moshi data classes
converts*
json something
4:55 PM
trocchietto_Ivano
Mark M.
ah, OK, an IDE plugin
trocchietto_Ivano
yep
5:00 PM
Mark M.
OK, that's all for today's chat
the next one is Tuesday in the 7:30pm US Eastern slot
trocchietto_Ivano
have a nice evening Mark, and Scott wish you some nice time. Thank you very much Mark!
Mark M.
have a pleasant day!
trocchietto_Ivano
thanks
Scott W.
has left the room
trocchietto_Ivano
has left the room
Mark M.
turned off guest access

Thursday, April 8

 

Office Hours

People in this transcript

  • Mark Murphy
  • Scott Wehby
  • trocchietto_Ivano