Apr 10 | 3:50 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Apr 10 | 4:00 PM |
Scott W. | has entered the room |
Mark M. |
hello, Scott!
|
Mark M. |
how can I help you today?
|
Scott W. |
hello
|
Scott W. |
I've got 3 topics to ask about
|
Scott W. |
1. I'm trying to implement a text view widget that can be read aloud and will highlight the word that's being read.
|
Scott W. |
I've got TextToSpeech working to read the contents of a TextView
|
Scott W. |
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
|
Apr 10 | 4:05 PM |
Mark M. | |
Mark M. |
that answer shows the "how do I highlight words?" part
|
Mark M. |
in a nutshell, you set and clear spans on a SpannableString
|
Mark M. |
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
|
Mark M. |
that might be a touch more efficient
|
Mark M. |
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
|
Mark M. |
(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.
|
Apr 10 | 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!
|
Mark M. |
Ivano: how can I help you today?
|
trocchietto_Ivano |
cool i have bullet questions
|
trocchietto_Ivano |
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*
|
trocchietto_Ivano |
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
|
Mark M. |
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
|
Mark M. |
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.
|
Scott W. |
I've implemented a drawing system using a third party library before, and it takes a lot of work to make it look ok.
|
Apr 10 | 4:15 PM |
Scott W. |
Do you know of a best way to accomplish the drawing part of this task?
|
Scott W. |
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...
|
Mark M. |
I don't know how you are defining "standard libraries" in this context
|
Mark M. |
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.
|
Scott W. |
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
|
Mark M. |
OK, I'll be back with you in a bit
|
Mark M. |
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
|
trocchietto_Ivano |
volatile
|
trocchietto_Ivano |
in this way
|
trocchietto_Ivano |
View paste
(6 more lines)
|
trocchietto_Ivano |
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
|
trocchietto_Ivano |
ok
|
trocchietto_Ivano |
thanks
|
Apr 10 | 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
|
trocchietto_Ivano |
sorry
|
trocchietto_Ivano |
did not want to press enter was preparing the question
|
trocchietto_Ivano |
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
|
Mark M. |
Ivano: if you want to try again for that next question, go ahead!
|
trocchietto_Ivano |
ok
|
trocchietto_Ivano |
View paste
|
Apr 10 | 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
|
trocchietto_Ivano |
I tried but did not work
|
Mark M. |
is it technically possible? perhaps
|
Mark M. |
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
|
trocchietto_Ivano |
I see
|
trocchietto_Ivano |
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
|
trocchietto_Ivano |
so I should use dagger?
|
Mark M. |
Dagger is complex
|
Mark M. |
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
|
trocchietto_Ivano |
thanks
|
Mark M. |
sure!
|
Mark M. |
Scott: are you now de-interrupted? :-)
|
trocchietto_Ivano |
lol
|
Apr 10 | 4:30 PM |
Scott W. |
yes
|
Scott W. |
My question is about fragments and possibly inheritance
|
Scott W. |
my app has 8 similar fragments. This is a single activity application
|
Scott W. |
lots of the fragments are split into 3 sections vertically with the top and bottom being the same, but the middle is different
|
Scott W. |
the fragment navigation is being managed by the navigation xml
|
Scott W. |
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
|
Apr 10 | 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
|
Mark M. |
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
|
Scott W. |
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
|
trocchietto_Ivano |
thanks
|
Apr 10 | 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
|
trocchietto_Ivano |
good one, better than search for my habits
|
trocchietto_Ivano |
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
|
trocchietto_Ivano |
so I will do
|
Mark M. |
yes, having a decent IDE can help
|
Mark M. |
Scott: back to you! do you have another question?
|
Scott W. |
yeah I've got a few simple kotlin questions.
|
Scott W. |
In a Kotlin file, there can be constants defined above the class declaration
|
Scott W. |
but then constants are also defined in the companion object
|
Apr 10 | 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
|
Mark M. |
if the value is needed as part of an API, put it as a constant in a companion object, for namespacing
|
Mark M. |
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
|
Mark M. |
so, if you have Foo.kt that has LOG_TAG in it, I think it turns into FooKt.LOG_TAG in Java
|
Mark M. |
but I do very little Java interop nowadays, so I may be mis-remembering
|
Mark M. |
(i.e., I'd have to look it up in my own book)
|
Scott W. |
got it
|
Scott W. |
next kotlin question is... should views I want to hold onto as member variables be defined with the lateinit keyword?
|
Scott W. |
lateinit seems like a bad thing to do for some reason.
|
Scott W. |
like it's anti-kotlin
|
Mark M. |
um, well, that depends completely on when you are going to do the init :-)
|
Mark M. |
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
|
Mark M. |
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
|
Apr 10 | 4:50 PM |
Scott W. |
all right that's all for me today. Thanks for the help!
|
Mark M. |
you're welcome!
|
Mark M. |
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?
|
trocchietto_Ivano |
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?
|
trocchietto_Ivano |
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
|
trocchietto_Ivano |
that is why you use try catches in the activity!!!
|
trocchietto_Ivano |
checkmate
|
Mark M. |
there are other approaches, such as EitherNet: https://github.com/slackhq/EitherNet
|
Mark M. |
basically, it tries to strike a middle ground between raw Response objects and the exceptions
|
Mark M. |
it gives you a standard sealed class and standard conversions of response codes to Failure types
|
Mark M. |
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
|
trocchietto_Ivano |
converts*
|
trocchietto_Ivano |
json something
|
Apr 10 | 4:55 PM |
trocchietto_Ivano | |
Mark M. |
ah, OK, an IDE plugin
|
trocchietto_Ivano |
yep
|
Apr 10 | 5:00 PM |
Mark M. |
OK, that's all for today's chat
|
Mark M. |
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 |