[SetupWizard] Setup Wizard crash on scrolling the list in Select Wi-Fi

screen

 - Setupwizard was crashing because RecyclerView during keyboard scrolls
   invokes onCreateViewHolder(ViewGroup, int) for header view more than
   once. We return the same headerView object each time which causes
   problems later on.
 - Fixed the problem by wrapping the header in a framelayout and
   inserting the header to the current framelayout in
   onBindViewHeader(ViewHolder, int).

Testing:
-------
 - Verified by running on Pixel C, no crashes observed
 - Also attempted scrolling using touchscreen, works as usual.
bug:30789424
Change-Id: I89ac09e14f21ceec3628f249f2cd2a391f020072
This commit is contained in:
Ajay Nadathur 2016-08-16 16:38:20 -07:00
parent 64f2ad2e53
commit c3a97eece3

View file

@ -25,6 +25,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
import com.android.setupwizardlib.DividerItemDecoration;
import com.android.setupwizardlib.R;
@ -102,8 +103,21 @@ public class HeaderRecyclerView extends RecyclerView {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
/*
* Returning the same view (mHeader) results in crash ".. but view is not a real child."
* The framework creates more than one instance of header because of "disappear"
* animations applied on the header and this necessitates creation of another headerview
* to use after the animation. We work around this restriction by returning an empty
* framelayout to which the header is attached using #onBindViewHolder method.
*/
if (viewType == HEADER_VIEW_TYPE) {
return new HeaderViewHolder(mHeader);
FrameLayout frameLayout = new FrameLayout(parent.getContext());
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT
);
frameLayout.setLayoutParams(params);
return new HeaderViewHolder(frameLayout);
} else {
return mAdapter.onCreateViewHolder(parent, viewType);
}
@ -115,7 +129,14 @@ public class HeaderRecyclerView extends RecyclerView {
if (mHeader != null) {
position--;
}
if (position >= 0) {
if (holder instanceof HeaderViewHolder) {
if (mHeader.getParent() != null) {
((ViewGroup) mHeader.getParent()).removeView(mHeader);
}
FrameLayout mHeaderParent = (FrameLayout) holder.itemView;
mHeaderParent.addView(mHeader);
} else {
mAdapter.onBindViewHolder(holder, position);
}
}