Status Update
Comments
yb...@google.com <yb...@google.com>
da...@gmail.com <da...@gmail.com> #2
yb...@google.com <yb...@google.com> #3
Branch: androidx-master-dev
commit 41c9e54ce4ab51f95d19a55fa92a56b6bd018c62
Author: Ian Lake <ilake@google.com>
Date: Mon Mar 23 16:07:32 2020
Allow obfuscation of kept Fragments
Fragments that are kept solely by class
can safely be obfuscated.
By switching to keepclasseswithmembers,
only classes with a default constructor
will qualify to be kept. This also allows
shrinking of classes that are constructed
through a custom FragmentFactory.
Test: tested in sample app at
BUG: 151605338
Change-Id: I68ea8779bce80f33f27658cf87a94ccede5376b0
M fragment/fragment/proguard-rules.pro
yb...@google.com <yb...@google.com> #4
While -keepclassmembers
caused a regression in the allowsObfuscation
to allow even kept fragments to be obfuscated.
This will be available in the upcoming Fragment 1.2.4
and 1.3.0-alpha03
.
yb...@google.com <yb...@google.com> #5
The new release 1.2.4 now leads to a direct crash on app-start, i.e. when Android tries to inflate any Fragment referenced in the main navigation graph.
da...@gmail.com <da...@gmail.com> #6
Re #5 - please file a new bug with a sample project that reproduces your issue.
ap...@google.com <ap...@google.com> #7
This change in 1.2.4 also leads to ClassNotFoundException when a fragment is created by providing a name attribute to a FragmentContainerView if the referenced fragment class name is not explicitly kept and obfuscation is enabled:
<androidx.fragment.app.FragmentContainerView
...
android:name="fullClassName"
... />
This, of course, is the expected behavior, but I think it is too much of an API-breaking change for a patch release.
yb...@google.com <yb...@google.com> #8
Re #7 - please make sure you've followed the instructions in FragmentContainerView
referenced classes as per the
If you're using Android Gradle Plugin 4.1 Canary 4 or higher and you're not getting your classes properly kept and non-obfuscated when using FragmentContainerView
, please
da...@gmail.com <da...@gmail.com> #9
Re #6: It's essentially
yb...@google.com <yb...@google.com> #10
Thanks everyone
da...@gmail.com <da...@gmail.com> #11
I could use NO_ISOLATION or find another way to handle view types, maybe. I just wanted to do as less changes to the paging and recycler view classes and APIs as possible. Thank you for original fix, though. It would help a bit.
Also about ViewHolder.getBindingAdapterViewType(), yeah it sounds a bit off, but maybe Concat adapter should have the method like getBindingAdapterViewType(globalViewType). I haven't dig much into Concat adapter API, but I saw that you have some kind of map between local and global types and I suppose ViewTypeLookup could convert types for both strategies (Isolation and Shared) (ViewTypeStorage in API). Also ViewTypeStorage have the method like
NestedAdapterWrapper getWrapperForGlobalType(int globalViewType)
So seems like you can have adapter wrapper without using a position, like in getItemViewType(int position) in the original RV API. Maybe you can add open method to get local view type by using global.
The ConcatAdapterController already uses similar feature when it creates view holder (or triggers VH creation)
public ViewHolder onCreateViewHolder(ViewGroup parent, int globalViewType) {
NestedAdapterWrapper wrapper = mViewTypeStorage.getWrapperForGlobalType(globalViewType);
return wrapper.onCreateViewHolder(parent, globalViewType);
}
I may read the code wrong, but at a glimpse there is could be possibility to get local view type without using position, just global view type which I can get from VH.
yb...@google.com <yb...@google.com> #12
yea that could be as well. I've been trying to set up concat adapter to be as seemless as possible to the nested adapter but it does hit these cases where an explicit API becomes necessary :/.
If we were to provide this API in concat adapter, then the container adapter still needs to know that it is part of a concat adapter (and a reference to it) so I'm not sure how useful it will be (compared to also keeping a map or field in the VH yourself). Which is why i like the NO_ISOLATION solution better (and if you use layout ids as item types, that is usually good enough unless you have different VHs with the same layout)
But i guess you cannot use no isolation w/ the paging adapter :/ (though paging adapter is actually a very simple wrapper:
Description
Component used: ConcatAdapter
Version used: 1.2.0
Devices/Android versions reproduced on: any
The case is about two methods onViewRecycled and onFailedToRecycleView in ConcatAdapter. If you see the documentation of the base recycler view adapter it said that I can get a view holder position before it will be recycled by using ViewHolder#getBindingAdapterPosition() inside those two methods. But now comes ConcatAdapter who intercept those calls and execute its own code before it re-route them to nested adapters. The concat adapter executes the line which is removes viewHolder from mBinderLookup.
Concat Adapter triggers ConcatAdapterController.onViewRecycled:
The problem then comes out in nested adapter when I'm trying to get a view type of the view holder which is about to recycle:
I use holder.getBindingAdapterPosition() and receive NO_POSITION, of course. Because the Concat Adapter throws my call through ConcatAdapterController again by triggering getLocalAdapterPosition:
This method using mBinderLookup to search for the NestedAdapterWrapper for this view holder (mBinderLookup.get(viewHolder)), but the thing is that it is already gone, it was removed a moment ago in ConcatAdapterController.onViewRecycled. So now I do not see a possibility to get local view type using just a view holder in my nested adapter onViewRecycled method. And I can't use global view type from the view holder itself, because I'm using isolateViewTypes = true.
Even though the current implementation does not match the documentation of recycler view, I don't see how to use multiple view types for the nested adapter in isolation mode.