Status Update
Comments
yb...@google.com <yb...@google.com> #2
yb...@google.com <yb...@google.com> #3
since it is already marked as deprecated, we can probably do it by now.
pa...@gmail.com <pa...@gmail.com> #4
yb...@google.com <yb...@google.com> #5
Branch: androidx-master-dev
commit d576cbdc911cba16638a44fd8223391a90a07ef7
Author: Mike Nakhimovich <digitalbuddha@users.noreply.github.com>
Date: Tue Aug 11 09:30:34 2020
[GH] Hide deprecated internal API.
## Proposed Changes
* `RoomDatabase.java` has protected `mCallbacks` field which is leaking in the API docs, we should @Hide it.
## Testing
Test: Ran unit tests locally
## Issues Fixed
Fixes: 76109329
This is an imported pull request from
Resolves #61
Github-Pr-Head-Sha: 6440daa3a63752c7f9d5ba2a390248cd85bc634f
GitOrigin-RevId: fe92d8466a59b44b218b6ca3cbd57dcda17992f7
Change-Id: Id599cdf5b02b32bdae0166266fb7da967598fe92
A room/runtime/api/current.ignore
M room/runtime/api/current.txt
M room/runtime/api/public_plus_experimental_current.txt
M room/runtime/api/restricted_current.txt
M room/runtime/src/main/java/androidx/room/RoomDatabase.java
pa...@gmail.com <pa...@gmail.com> #6
Yes you misunderstood
Because the ViewHolder cannot be get in the GridLayoutManager.SpanSizeLookup.getSpanSize(position: Int) method, the solution you provided is not available
My code is as follows:
interface SpanSizeAdapter {
fun getSpanSize(position: Int): Int
}
class MyGridLayoutManager(context: Context, spanCount: Int) : GridLayoutManager(context, spanCount) {
init{
super.setSpanSizeLookup(object : SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return getSpanSizeImpl(position)
}
})
}
private var recyclerView: RecyclerView? = null
override fun onAttachedToWindow(view: RecyclerView) {
super.onAttachedToWindow(view)
recyclerView = view
}
private fun getSpanSizeImpl(position: Int): Int {
val adapter = recyclerView?.adapter
if (adapter != null && position >= 0 && position < adapter.itemCount) {
val itemSpan = getSpanSizeFromAdapter(adapter, position)
return if (itemSpan == -1) spanCount else itemSpan.coerceAtLeast(1)
}
return 1
}
private fun getSpanSizeFromAdapter(adapter: RecyclerView.Adapter<*>, position: Int): Int {
return when (adapter) {
is SpanSizeAdapter -> {
adapter.getSpanSize(position)
}
is ConcatAdapter -> {
var startPosition = 0
val wrapperAdapter = adapter.adapters.find { childAdapter ->
val childAdapterEndPosition = startPosition + childAdapter.itemCount - 1
if (position in startPosition..childAdapterEndPosition) {
true
} else {
startPosition = childAdapterEndPosition + 1
false
}
} ?: throw IllegalArgumentException("Cannot find wrapper for $position")
val localPosition = position - startPosition
getSpanSizeFromAdapter(wrapperAdapter, localPosition)
}
else -> {
1
}
}
}
}```
As shown in the code above, when the instance of the adapter is ConcatAdapter, I need to get the adapter list by calling adapter.adapters, and then combine the position to get the wrapper adapter and localPosition.
Although I can achieve my goal now, by looking at the source code, I found that adapter.adapters will return a new ArrayList every time it is called, as follows:
```java
class ConcatAdapter {
....
/**
* Returns an unmodifiable copy of the list of adapters in this {@link ConcatAdapter}.
* Note that this is a copy hence future changes in the ConcatAdapter are not reflected in
* this list.
*
* @return A copy of the list of adapters in this ConcatAdapter.
*/
@NonNull
public List<? extends Adapter<? extends ViewHolder>> getAdapters() {
return Collections.unmodifiableList(mController.getCopyOfAdapters());
}
....
}
class ConcatAdapterController {
....
@SuppressWarnings("MixedMutabilityReturnType")
public List<Adapter<? extends ViewHolder>> getCopyOfAdapters() {
if (mWrappers.isEmpty()) {
return Collections.emptyList();
}
List<Adapter<? extends ViewHolder>> adapters = new ArrayList<>(mWrappers.size());
for (NestedAdapterWrapper wrapper : mWrappers) {
adapters.add(wrapper.adapter);
}
return adapters;
}
....
}
This is a bit expensive in the getSpanSize() method, so I hope there is a more economical way to get the wrapper adapter and localPosition based on the position, like this:
class ConcatAdapter {
@NonNull
public WrapperAndLocalPosition findWrapperAndLocalPosition(int position, WrapperAndLocalPosition wrapperAndLocalPosition) {
return mController.findWrapperAndLocalPosition(position, wrapperAndLocalPosition);
}
}
yb...@google.com <yb...@google.com> #7
Oh I see, you don't have access to the ViewHolder (and shouldn't because span size might be called w/o a view holder).
We cannot open up that API as is but we can create a similar public version that will allocate a new pair on each call (or C style API where you can pass the bundle but that is really ugly).
I looked around the code a bit but unfortunately i don't see an easy way to implement your use case, especially if you are adding/removing adapters to the concat adapter.
pa...@gmail.com <pa...@gmail.com> #8
I understand your concerns, I can accept the scheme of returning a Pair<RecyclerView.Adapter, Int>, which is already much less expensive than a new ArrayList. But if there are other difficulties and the pair cannot be added, I also accept it.
Thanks again.
ry...@google.com <ry...@google.com>
ap...@google.com <ap...@google.com> #9
Branch: androidx-main
commit 2c3abe7990031f05f064bcd5ce4ee9f4285e40b6
Author: Ryan Mentley <ryanmentley@google.com>
Date: Thu Aug 26 14:39:15 2021
Add ConcatAdapter.getWrappedAdapterAndPosition
Relnote: "New ConcatAdapter.getWrappedAdapterAndPosition method added to
allow for retrieving wrapped adapter information in situations where you
don't have a ViewHolder, such as a SpanSizeLookup"
Fixes: 191543920
Test: New ConcatAdapterTest.getWrappedAdapterAndPositionTest
Change-Id: I2bd4c99ee4417f0b3ed74d471ed732af24a2d1b3
M recyclerview/recyclerview/api/current.txt
M recyclerview/recyclerview/api/public_plus_experimental_current.txt
M recyclerview/recyclerview/api/restricted_current.txt
M recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterTest.kt
M recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/ConcatAdapter.java
M recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/ConcatAdapterController.java
Description
Due to business needs, you need to access the ConcatAdapterController.findWrapperAndLocalPosition(int) method when encapsulating the ConcatAdapter, so I hope to open the ConcatAdapterController.findWrapperAndLocalPosition(int) method in the ConcatAdapter