Office Hours — Today, March 23

Saturday, March 20

Mar 23
8:20 AM
Mark M.
has entered the room
Mark M.
turned on guest access
8:25 AM
Kai H.
has entered the room
Eric
has entered the room
Mark M.
hello, Kai and Eric!
Kai: you got here first, so... how can I help you today?
Kai H.
Hello Mark
Eric
morning :)
Kai H.
How do I know a suspend function can be safely suspended? Who decides that?
8:30 AM
Mark M.
how are you defining "safely suspended"?
8:30 AM
Kai H.
"not fucking something up" ;-)
Mark M.
in general, if your function is thread-safe, it should be safe for suspension
the one outlier case that I know if is if you are using ThreadLocal, as that gets a bit weird with suspension, but that's also fairly uncommon in ordinary app code
Jan
has entered the room
Kai H.
I know in usual threading other threads will run if a thread waits for IO for example.
Mark M.
(BTW, hello Jan -- I will be with you after Kai and Eric!)
Kai H.
but I just wondered who decides when to suspend a suspend function :)
Mark M.
"who decides" is some combination of the general coroutine framework and the dispatcher, AFAIK
and the suspension points are pretty much at the point of calling a suspend function
View paste
suspend fun foo() {
  doSomething()
  callASuspendFunction()
  doSomethingElse()
}
when foo() is called, the coroutine might be suspended
and if callASuspendFunction() is a suspend fun, the coroutine might be suspended when we make that call
8:35 AM
Mark M.
whether it will be suspended depends on whether there is another coroutine that is ready to run in the same dispatcher
Kai H.
So the idea is to say "if you hit a function marked with 'suspend' you may suspend it"?
Mark M.
pretty much
Kai H.
Sounds like something very basic that I managed to miss ;-)
Mark M.
I tried to cover it in the "Coroutines are Cooperative" section of *Elements of Kotlin Coroutines*, though I might not have done a good job there
Kai H.
I haven't read that yet, I think. Currently working through your Klassbook.
Mark M.
ah, yes, that's a book that you have in the Warescription
spoiler alert: it covers coroutines
let me take questions from the others, and I will get back to you a bit later
Kai H.
sure
thx
Mark M.
Eric: your turn! how can I help you today?
8:40 AM
Mark M.
Eric: do you have a question?
Eric: if you come up with a question, let me know!
in the meantime...
Jan: how can I help you today?
Jan
View paste
I'm looking for advice on how to get started learning Android Things SDK and Android Bluetooth.
I need some piece of hardware to test any Android code I write.

Do you know of any board I could buy for test purposes. Ideally, I'd want to be 
able to connect with it via Bluetooth LE then maybe make some lights flash or 
something else happen on the board.

I looked at adafruit.com but that seemed to be about programming the board.
I want to program Android phone to talk to the board.
Mark M.
well, unless the device is designed with a BLE protocol for flashing lights, you would need to program both sides
you have something on the board that exposes a BLE service, and you have something on the phone that connects to that service via BLE
if you want to get started just with BLE, choose an existing BLE protocol and write a client for it: heart rate monitor, blood pressure monitor, etc.
8:45 AM
Mark M.
because you can buy hardware that supports that protocol off the shelf and just talk to it
Jan
So any heart rate monitor I buy will send me its data via BLE service built-in?
Mark M.
well, if the heart-rate monitor is described as supporting Bluetooth, yes
there are other heart rate monitor protocols, like ANT+, that (AFAIK) aren't BLE
Jan
Okay. I hadn't realized manufacturers exposed how to talk to their device and get its data.
Mark M.
there are standards for BLE protocols
Jan
Great. Thanks for your help.
Eric
View paste (12 more lines)
I have this following navigation xml whose design view shows ListFragment overlapping ItemFragment.  If I test it ListFragment goes away and is not replaced by ItemFragment(onCeate is not invoked).  My fragments live in MainActivity which is a ConstraintLayout containing a FragmentContainerView referencing my navigation xml file

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    app:startDestination="@id/list_dest">

<fragment 
    android:id=“@+id/list_dest”
    android:name=“com.example.navigation.ListFragment”
    tools:layout=“@layout/fragment_list”>
        <action
            android:id=“@+id/next_action”
            app:destination=“@id/item_dest” />
 </fragment>
...
8:50 AM
Mark M.
OK, nothing seems too unusual with that nav graph
how are you navigating to that item_dest destination?
Eric
View paste
I am trying to use safeArgs plugin.  After a list item is selected I do
val action = ListFragmentDirections.nextAction("myName", "myDesc")
findNavController().navigate(action)
Mark M.
OK, that looks fine too
when you call this, do you get anything interesting in Logcat? perhaps navigation is catching some exception and logging it rather than re-throwing it, so your app does not crash
Eric
my navigation xml says "no navhostfragments found"
Mark M.
sorry, I do not know what you mean by "my navigation xml says" -- are you getting this message in the editor?
8:55 AM
Eric
View paste (5 more lines)
Yes, my design view of mobile_nav.xml complained.  But I reference it in my activity:
androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
        <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
...
Mark M.
I think that's an IDE bug -- I was seeing something like that too when using FragmentContainerView
however, despite the message, it still works -- my nav samples in my books use it
so, other than checking Logcat for interesting messages, the best that I can offer is for you to compare and contrast your apps with mine (see FragmentNav in *Elements of Android Jetpack*, for example), and try to see where the differences are
9:00 AM
Eric
ok I guess it isn't a reason ItemFragment didn't appear. In response to your question about errors in Logcat, I noticed an error reading "Invalid ID", but I can't tell my specific incorrect id
Mark M.
¯\_(ツ)_/¯
Eric
no problem, I'll keep looking
Mark M.
another thing to possibly try, if you are using Kotlin, is to replace the navigation XML resource with the Kotlin DSL, and see if you get better results
that also puts you closer to what Navigation for Compose uses, for if/when you migrate to Jetpack Compose in the coming years
but, let me take questions from the others, and I will try to get back to you before the end of the chat
Kai: back to you! do you have another question?
Kai H.
Yes
I have a mix of imported images (png, svg (Android xml)) and images loaded from a web server (png, svg, ...). How would you deal with that in a mostly uniform way?
Right now there is quite a bit of extra code in a couple of places to see where an image comes from and how it needs to be loaded.
9:05 AM
Kai H.
Also data classes that have both a "Android resource" field and a "url" field.
9:05 AM
Kai H.
And such.
Mark M.
View paste
sealed class ImageSource {
  data class Resource(@DrawableRes resourceId: Int) : ImageSource()
  data class Web(url: String) : ImageSource()
}
off the cuff, I would look to do something like that, then add an extension function to Glide/coil/Picasso to be able to load() an ImageSource
the code that defines where the image is really from creates the ImageSource.Resource or ImageSource.Web objects
the rest of the code just passes around an ImageSource as a largely-opaque object
Kai H.
*makes weird noises in Java*
I forgot to say that we're still using Java, but I guess the idea stays the same.
Mark M.
sorry, you were talking coroutines earlier and a data class in this question, so I assumed Kotlin
Kai H.
My bad.
Mark M.
but, yes, you could use an ImageSource interface or abstract class in Java for a similar sort of role
9:10 AM
Mark M.
in the end, you're creating an abstraction around the concept of where the image is coming from
and you're trying to constrain who all cares about the distinction of the image source, using the abstraction everywhere else
let me take questions from the others, and with luck I'll get back to you before the end of the chat
Jan: back to you! do you have another question?
9:15 AM
Mark M.
OK, if anyone has any questions, fire away! I'll try to handle whatever I can in the remaining chat time
Kai H.
If you had to use Java still, which version would you use and why?
Mark M.
if by "use" you mean syntax, Android only supports a subset of Java 8, so I would be focused there
if by "use" you mean the installed JDK, I am using 11 right now, due to some Robolectric problem IIRC
Eric
In ListFragment onCreateView I call an api to get data. If I click on an item to go to ItemFragment and press back I notice my api is called again. I cannot move my api call to onCreate because I get an error saying viewLifecycleOwner(using to observe my api result) must be used after onCreateView
Mark M.
"I notice my api is called again" -- the implication is that your fragment's view was destroyed and is now being recreated. Depending on the FragmentTransaction that was used, that is perfectly normal. If you wish to avoid the redundant API call, do that work in a Jetpack ViewModel and cache the results.
Eric
Do you have an example?
Mark M.
nothing published that I can think of
Eric
I am calling it from my viewmpdel. it is posting twice because of your reason
9:20 AM
Mark M.
either make the call in the init block of the viewmodel, or give the viewmodel more smarts to cache the result and return the cache if called a second time
Eric
ok I appreciate it
9:25 AM
Kai H.
I am still confused by the java support. What is it that is supported in Version 9, 10 and such regarding this article? https://jakewharton.com/androids-java-9-10-11-a...
Isn't it the syntax?
Mark M.
I don't think any of that is officially supported. It works, and some might not break because it's transparent to Android via the javac compiler. But there might be IDE hiccups, etc., if the Android tools team is not thinking about them.
that is all syntax, though newer JDKs also have newer classes that are not in the Android SDK
9:30 AM
Jan
has left the room
Mark M.
OK, that's a wrap for today's chat
Eric
thanks mark
Kai H.
Have a good time and stay healthy.
Mark M.
the transcript will go up on https://commonsware.com/office-hours/ shortly
Eric
has left the room
Kai H.
Thanks
Mark M.
the next chat is Thursday in the 7:30pm US EDT slot
have a pleasant day!
Kai H.
has left the room
Mark M.
turned off guest access

Saturday, March 20

 

Office Hours

People in this transcript

  • Eric
  • Jan
  • Kai H.
  • Mark Murphy