Office Hours — Today, May 26

Saturday, May 23

Mark M.
has entered the room
Mark M.
turned on guest access
May 26
7:30 PM
Kai H.
has entered the room
Kai H.
hi there
Mark M.
hello, Kai!
how can I help you today?
Kai H.
I have a rather extensive architecture question about (contextual) action bars
Mark M.
if you mean "action modes", I haven't played with those in a few years, so I may be a bit rusty, but go ahead!
Kai H.
I have a list with item of different types
Like pictures, pdfs, word documents etc.
I can long click the items to select and I can select multiple items
Depending on which types of items are selected, I wanna offer some actions in the ActionBar.
I wonder how to design and organize the classes
7:35 PM
Mark M.
I don't really have enough to go on to really help with that -- for example, what classes are you referring to?
Eric
has entered the room
Kai H.
The classes needed to do something like that
Mark M.
(BTW, hello Eric! I'll be with you shortly!)
Eric
ok mark
Mark M.
Kai: um, well, that's kinda broad
your first challenge is in deciding how to track the multiple selections
Kai H.
I feared so
Mark M.
Google has a recyclerview-selection library
I tried it once and didn't have a lot of luck with it
I show how to roll your own in *The Busy Coder's Guide to Android Development*, in the Advanced RecyclerView chapter
Kai H.
I think the usual way is to have a list of selected items that are just added and removed on the callback in the adapter.
Mark M.
and I'm sure there are third-party libraries for it, though I haven't had a need for this recently so I can't name any
well, your ViewHolder is going to need to know whether an item is selected or not, so it can render it appropriately (e.g., alternative background color)
what recyclerview-selection, my book samples, and stuff try to do is decouple the "track the selections" somewhat separately from the model data
that way, the selection logic can be reusable
but that's tricky to get right, and I don't think my book examples necessary handle all the edge cases
(er, necessarily handle)
7:40 PM
Mark M.
your activity/fragment that shows the toolbar will also need to know about the number and type of selections, so it can make your choices about what to show in that toolbar for options
which is why figuring out how you are going to track what is and is not selected is your first order of business, IMHO
now, a lot of the early RecyclerView work predated the Jetpack ViewModel system
(such as my aforementioned book examples)
so there may be some cleaner options nowadays than what we had, though RecyclerView itself makes some aspects messy
but, figuring out how to handle multiple selection in a RecyclerView with a modern architecture alone would be a thing I'd probably spend a few hours researching
let alone what the current approach is for a contextual action bar
Kai H.
Ok
Mark M.
(cause the system action modes never played well with Toolbar -- I'm assuming you'd use two Toolbar widgets and animate between them)
so, I'm sorry, but I don't have an "out of the box" solution to offer you on that subjec
let me take a question from Eric, and I'll swing back to you in a bit
Eric: your turn! how can I help you today?
Eric
I am reading "Elements of Room", "Relations in Room". I have a data class doubling as a Retrofit model and Room entity. My api returns a List<Category>. My Category data class contains a List<Book> for retrofit. I marked it Ignore.
Mark M.
"I have a data class doubling as a Retrofit model and Room entity" -- that's unlikely to turn out well, unless you have complete control over the server
7:45 PM
Mark M.
if you do control everything, then you can force yourself to keep things consistent
Eric
I reuse it because my function gets data from an api and persists it into room. I am confused about any alternative using separate classes for retrofit/room
Mark M.
if you do not control everything, I strongly recommend that you treat your Retrofit classes as separate DTOs (data transfer objects) from your Room entities
Eric
my question is actually my associated Books do not get persisted
Kai H.
has left the room
Eric
I followed the example you gave by creating a Books entity. I created a CategoryAndBooks data class
Mark M.
well, properties with @Ignore get ignored :-)
OK, that sounds fine
Eric
I see. Is there a way to persist the associated books using the pattern you demonstrated
Mark M.
but you need to persist the Book objects yourself
is this a one-to-many or a many-to-many relation?
7:50 PM
Eric
in CategoryDao I only insert categories. Are you saying I need a BooksDao to inisert books?
Mark M.
you need DAO functions for your books, yes
Eric
I think it is one to many. my api returns a List<Category>. One Category is related to many Books
Mark M.
and a Book has only one Category?
Eric
yep
Mark M.
then yes, that is a one-to-many relation
if you look at my chapter on "Room Relations", my "One-to-Many Relations" section shows a Bookstore DAO
Eric
I ignore my List<Book> in my Category because as you write in your book it cannot persist similarly to retrofit deserializing nested model
yes I follow it. It does not contain a Dao for books iirc
Mark M.
Bookstore handles Category and Book
a DAO is not limited to a single entity type
so, my Bookstore offers save() functions for Category and Book
Eric
can you explain suspend?
Mark M.
and my test code shows saving a Category and saving Book objects in separate calls
the suspend keyword is part of Kotlin coroutines
7:55 PM
Mark M.
I happen to be using Kotlin and coroutines in this book, as it is the long-term direction that Android is going in terms of thread management, but Room is not tied to coroutines
as part of the Warescription, you also have access to *Elements of Kotlin Coroutines*
you might want to read the first couple of chapters there, to get familiarized with the basics, like the role of the suspend keyword
also, *Elements of Kotlin Coroutines* has an appendix on migrating an app from using RxJava to coroutines
8:00 PM
Eric
ok great
Mark M.
while RxJava may not matter to you, the resulting app demonstrates using Room and Retrofit together, with separate classes
since Kai departed, if you have other questions, go right ahead!
Eric
thank you. I am rereading your example and applying it.
8:10 PM
Eric
it looks like if you want to persist a categorie's associated books you execute 2 queries, 1 to insert the category followed by 1 to insert related books
Mark M.
yes
remember: a Category does not have any List<Book>
that is one of the reasons why I do not like using the same classes for Retrofit and Room
in Retrofit, you might very well be in a situation where Category has a List<Book>
Eric
So I have a completable insertCategories and a completable insertBooks. For each category, I want to persists category and its related books
Mark M.
you would need to set up a DAO function that takes those books (List<Book>, vararg Book, Array<Book>, whatever) and arrange to call that function
8:15 PM
Eric
yes. if my Category contains a List<Book> I ignore it and created a Book entity. Are you saing it doesnt work? After I get a List<Category> I want to save my category and its List<Book>
ok. so I got 2 Completables
Mark M.
"Are you saing it doesnt work?" -- I am saying that Room is going to ignore that List<Book>
and I fear that it will confuse you a fair bit going forward
if you want to persist a Category and its List<Book>, the safest thing to do is to have a single @Transaction function on your DAO that turns around and calls the DAO functions for those individual persistence operations
that way, the entire thing succeeds or fails as a whole
I have a section on @Transaction in "The DAO of Entities" chapter: https://wares.commonsware.com/app/internal/book...
8:20 PM
Eric
ok, so it first persists book, then iterates its List<Book> to persist every associated book?
Mark M.
well, a DAO function can take a List<Book>
so, you would have one DAO function that takes a Category and a separate DAO function that takes a List<Book>
and, ideally, you would wrap those two calls in a single function with the @Transaction annotation, and that function is basically the "public API" that you call to save a Category
Eric
ok great. You mentioned retrofit and room using distinct models. I would need to convert between a retrofit data class and room data class?
8:25 PM
Mark M.
probably
8:25 PM
Mark M.
I say "probably" because it depends a lot on what your app is doing
I typically think of three separate data representations:
1. the real model objects that I want to use in the UI
2. the Room entities
3. the Retrofit responses
Eric
I appreciate it; you gave me lots to consider today. take it easy
Mark M.
these will have similar pieces of data but will have them organized differently, to take into account Room's restrictions and your server team's Web service API design
I wish you luck with your project, and I hope to see you in a future chat!
Eric
has left the room
8:30 PM
Mark M.
turned off guest access

Saturday, May 23

 

Office Hours

People in this transcript

  • Eric
  • Kai Hatje
  • Mark Murphy