Apr 2 | 8:25 AM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Kai H. | has entered the room |
Mark M. |
hello, Kai!
|
Kai H. |
Hello
|
Mark M. |
how can I help you today?
|
Kai H. |
When something gets shared to my app, I use a Cursor, query() and eventually getString() to get the DISPLAY_NAME
|
Kai H. |
for the shared content.
|
Apr 2 | 8:30 AM |
Kai H. |
I have found a case where DISPLAY_NAME is not set though.
|
Apr 2 | 8:30 AM |
Mark M. |
I was about to point out that possibility
|
Mark M. |
not everything will support the OpenableColumns, of which DISPLAY_NAME is one
|
Kai H. |
What would be the fallback in that case?
|
Mark M. |
getLastPathSegment() on the Uri, perhaps
|
Mark M. |
for a Uri of the form content://authority.goes.here/hey/this/seems/ni..., getLastPathSegment() returns nice.jpg
|
Mark M. |
however, for a Uri of the form content://authority.goes.here/who/is/number/1, getLastPathSegment() returns 1
|
Kai H. |
It's a content uri with a number and the end and no file type.
|
Mark M. |
then you get to make something up, I guess
|
Kai H. |
I have noticed that another app somehow gets the right file name. I did wonder how.
|
Kai H. |
If there is some other query I can do or something.
|
Mark M. |
can you paste the actual Uri here?
|
Kai H. |
Unfortunately the "other app" is not open source
|
Kai H. |
Sec
|
Kai H. |
Working on it :D
|
Apr 2 | 8:35 AM |
Kai H. |
"content://media/external/file/764" in this case. I guess I can get the actual file name for that?
|
Mark M. |
I would have expected DISPLAY_NAME to work for that
|
Mark M. |
that should be from MediaStore
|
Kai H. |
It's the "Huawei Files" file explorer that doesn't work for me.
|
Mark M. |
is the other app that works a Huawei app?
|
Kai H. |
No, it's "total commander"
|
Mark M. |
you could try querying for the DATA column
|
Mark M. |
that's deprecated as of Android 10 and was never reliable
|
Mark M. |
but, it might return a filesystem path corresponding to this item
|
Mark M. |
and while you may not have filesystem access to the content, the path will give you a filename
|
Kai H. |
So the way to go is to try every possible way and experimentally determine which one gives the best file name? (setting a default if nothing "proper" is returned).
|
Kai H. |
I was fearing as much, but still hoping for a "one fits all" solution
|
Mark M. |
I'd phrase it more as trying a priority-ordered series of approaches
|
Mark M. |
and taking the first one that returns something reasonable
|
Mark M. |
but there is no "one fits all" solution
|
Mark M. |
because this area is a mess and has been for *years*
|
Kai H. |
I see
|
Kai H. |
I do have another question
|
Apr 2 | 8:40 AM |
Mark M. |
go ahead!
|
Kai H. |
I am making a form to forward something to several users in a specific order. The current idea is to have two tabs, one with general settings and one with the changeable list of users.
|
Kai H. |
So you input the general information, then you go to the second tab and add as many users as you like, change the order of them until they are how you like and then you can send it all.
|
Kai H. |
I do struggle on how to implement the "list of users" inside the ScrollView that usually makes up such forms for the app.
|
Mark M. |
"list" usually implies a RecyclerView, not a ScrollView
|
Kai H. |
And how to implement the ordering of users (drag and drop? arrows on the items? ...) and deletion and such.
|
Mark M. |
you can use gestures (drag-and-drop reordering, swipe-to-delete) or visual controls (up/down arrows for reordering, X or trash can or something to delete)
|
Mark M. |
if your user base will tend to be "digital natives", they probably know to try gestures like that, and you have less visual clutter, though the implementation is more complex
|
Kai H. |
I was looking into ReyclerView with GestureHelper (or something), alternatively the approach with the arrows.
|
Kai H. |
All of it in a NestableScrollView
|
Kai H. |
Well, our user bsae is not digital native ;-)
|
Mark M. |
if your user base might include a fair number of people who are not super-familiar with touchscreen interfaces, the visual controls are more discoverable
|
Apr 2 | 8:45 AM |
Kai H. |
And we use visual controls throughout the app, so I would stay with that for now.
|
Mark M. |
that sounds reasonable, though the NestableScrollView might not be necessary -- that's only needed if you have other things on that tab besides the list
|
Kai H. |
I will have a EditText for adding a user name
|
Kai H. |
For example
|
Kai H. |
And some additional information for the user.
|
Mark M. |
another approach for that would be to have an "Add" item in the RecyclerView, which when clicked displayed a DialogFragment
|
Mark M. |
if you did not want all of that to be in one big scrollable thing
|
Kai H. |
And then have an edit button for the individual entries.
|
Mark M. |
yes
|
Mark M. |
if you were planning on using that form for edits... IMHO, that would be awkward
|
Kai H. |
The last one is actually my current favourite for a prototype implementation.
|
Kai H. |
All Content should always be displayed, which is why we use a ScrollView at the base. I found out that having a ListView inside of that is usually a bad idea.
|
Apr 2 | 8:50 AM |
Mark M. |
ListView is very old and does not know about nested scrolling
|
sudokai | has entered the room |
Kai H. |
That was a bit unclear: We have content on the form and when there is more content than display, the view should be scrollable, hence the Scrollview back then.
|
Kai H. |
Hi Kai ;-)
|
sudokai |
Hi! :)
|
Mark M. |
Kai: I think our new user is claiming root privileges over you... so I'll be back with you shortly!
|
Mark M. |
sudokai: hi! how can I help you today?
|
sudokai |
Oh, no go ahead you guys first!
|
sudokai |
I'm still trying to find my code
|
Kai H. |
Hehe. Been there...
|
Kai H. |
Yes. RecyclerView does know about NestedView, but is harder to set up and all. Especially when TabHosts with ViewPager(2) comes into play...
|
Mark M. |
OK, chime in when you are ready!
|
Mark M. |
Kai: agreed, which is why I tend to prefer keeping the list purely a list and using something else for additional data collection (e.g., the DialogFragment)
|
Mark M. |
but, that is really the decision of your graphic designers or whoever is making the UX choices
|
Mark M. |
(IOW, not me)
|
Kai H. |
I try to get some code out before they can make things too complicated :D
|
Kai H. |
But I'll take that as a recommendation and implement it simple at first, with something else for data collection.
|
Apr 2 | 8:55 AM |
Kai H. |
But then I'll either need to not use a ScrollView at that place or use something other than a ListView for the list, right?
|
Mark M. |
correct
|
Mark M. |
both ScrollView and ListView are original API Level 1 widgets and are not well-suited for nested-scrolling scenarios
|
Kai H. |
Ok. Thank you.
|
Apr 2 | 9:15 AM |
sudokai |
Mark, regarding the RecyclerView.ViewHolder RxJava subscription I mentioned last time, I'm really not sure how I can fix it.
|
sudokai |
I guess I need to rewrite the RecyclerView
|
sudokai |
Because I have 3 separate streams of data
|
sudokai |
The list itself and 2 more
|
Mark M. |
these are Observable? Flowable? something else?
|
sudokai |
Flowable I believe
|
sudokai |
I mean, there's no view model for the recyclerview
|
sudokai |
It's connected directly to a Realm list
|
Apr 2 | 9:20 AM |
sudokai |
Then there's some sort of event bus that emits updates
|
sudokai |
So the subscriptions are created in the viewholder
|
Mark M. |
when you say "it's connected directly to a Realm list", what do you mean?
|
Mark M. |
do you mean that you are observing a Flowable from Realm and are using that to update the RecyclerView?
|
sudokai |
Well, Realm provides a class called RealmRecyclerViewAdapter
|
Mark M. |
ah
|
sudokai |
And my RecyclerView.Adapter is extending that
|
Mark M. |
one option would be to not do that :-)
|
sudokai |
Then in their base class, they hook up some realm change listeners, so it's sort of automagic
|
Mark M. |
I forget Realm's RxJava API, as it's been a while since I used it
|
Apr 2 | 9:25 AM |
sudokai |
Because Realm emits the changes to the collection
|
sudokai |
Then RealmRecyclerViewAdapter updates the view
|
Mark M. |
but if they have a way of giving you an Observable or Flowable for those changes, then you can use combineLatest() to assemble the RecyclerView contents from all of your observable sources (Realm, event bus, etc.)
|
Mark M. |
(combineLatest() being a static method on Flowable and Observable)
|
sudokai |
Because my data is not in a single Realm object, that's why there are 2 manually created subscriptions in the ViewHolder. Just giving you some context...
|
sudokai |
Okay, I'll check that
|
Mark M. |
to avoid ViewHolders needing to subscribe to RxJava, the general approach I would take is:
|
Mark M. |
1. Use a single observation system consistently (e.g., RxJava vs. RxJava + Realm-specific stuff)
|
Mark M. |
2. Combine your multiple reactive sources when any of them emit (e.g., combineLatest())
|
Mark M. |
3. Have that combined result be a List of pure data that represents what goes in the RecyclerView
|
Mark M. |
4. Observe that combined reactive source in your activity/fragment
|
sudokai |
Thanks a lot, I'll take a look, makes sense
|
Mark M. |
5. Have your RecyclerView.Adapter subclass ListAdapter, with a suitable DiffUtil.ItemCallback
|
sudokai |
Then I need a single source
|
sudokai |
Yeah
|
Mark M. |
6. Call submitList() on the adapter when the combined reactive source emits a new list
|
Mark M. |
the ListAdapter is set up to only modify the UI where needed, based on what is visible
|
sudokai |
Oh, I remember this example in your book
|
sudokai |
Thanks
|
Mark M. |
I definitely have some ListAdapter examples, though probably not one combining three reactive data sources
|
Apr 2 | 9:30 AM |
Mark M. |
and, that's all the time that I have for today, so that's a wrap for today's chat
|
Mark M. |
the next chat is Saturday at 4pm US Eastern
|
Mark M. |
have a pleasant day, and stay healthy!
|
Kai H. |
Same :)
|
Kai H. | has left the room |
sudokai | has left the room |
Mark M. | turned off guest access |