From c2dacf1b75f5f641dc5e0fa028d5f6d32ef114d3 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Fri, 27 May 2022 00:20:45 +0800 Subject: [PATCH] Fix flicker for AppDataUsage when zero usage When the page is entered from the AppInfoDashboardFragment, there is no way to know whether the cycle data is available before finished the async loading. If it's zero usage, the cycle spinner will be removed, which cause a flicker. Temporarily disable the preference list's animator before initial page updates can solve this issue. This also fix another flicker on this page when the background data is off. Fix: 233963355 Test: manual visual test Change-Id: I795ed95e15bb3216fa17adfd4f57faf5fd92fa00 --- .../settings/datausage/AppDataUsage.java | 32 +++++++++++++++++++ .../settings/datausage/AppDataUsageTest.java | 2 ++ 2 files changed, 34 insertions(+) diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java index f0d27997ff8..d57a2a18f79 100644 --- a/src/com/android/settings/datausage/AppDataUsage.java +++ b/src/com/android/settings/datausage/AppDataUsage.java @@ -40,6 +40,8 @@ import androidx.loader.content.Loader; import androidx.preference.Preference; import androidx.preference.Preference.OnPreferenceChangeListener; import androidx.preference.PreferenceCategory; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; import com.android.settings.applications.AppInfoBase; @@ -105,6 +107,7 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC private Context mContext; private ArrayList mCycles; private long mSelectedCycle; + private boolean mIsLoading; @Override public void onCreate(Bundle icicle) { @@ -226,6 +229,16 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC @Override public void onResume() { super.onResume(); + // No animations will occur before: + // - LOADER_APP_USAGE_DATA initially updates the cycle + // - updatePrefs() initially updates the preference visibility + // This is mainly for the cycle spinner, because when the page is entered from the + // AppInfoDashboardFragment, there is no way to know whether the cycle data is available + // before finished the async loading. + // The animator will be set back if any page updates happens after loading, in + // setBackPreferenceListAnimatorIfLoaded(). + mIsLoading = true; + getListView().setItemAnimator(null); if (mDataSaverBackend != null) { mDataSaverBackend.addListener(this); } @@ -297,7 +310,25 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC } } + /** + * Sets back the preference list's animator if the loading is finished. + * + * The preference list's animator was temporarily removed before loading in onResume(). + * When need to update the preference visibility in this page after the loading, adding the + * animator back to keeping the usual animations. + */ + private void setBackPreferenceListAnimatorIfLoaded() { + if (mIsLoading) { + return; + } + RecyclerView recyclerView = getListView(); + if (recyclerView.getItemAnimator() == null) { + recyclerView.setItemAnimator(new DefaultItemAnimator()); + } + } + private void updatePrefs(boolean restrictBackground, boolean unrestrictData) { + setBackPreferenceListAnimatorIfLoaded(); final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfMeteredDataRestricted( mContext, mPackageName, UserHandle.getUserId(mAppItem.key)); if (mRestrictBackground != null) { @@ -448,6 +479,7 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC } else { bindData(0 /* position */); } + mIsLoading = false; } @Override diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java index 14431ee5e69..483d74638a7 100644 --- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java +++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java @@ -48,6 +48,7 @@ import androidx.fragment.app.FragmentActivity; import androidx.preference.Preference; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; +import androidx.recyclerview.widget.RecyclerView; import com.android.settings.applications.AppInfoBase; import com.android.settings.testutils.FakeFeatureFactory; @@ -240,6 +241,7 @@ public class AppDataUsageTest { ReflectionHelpers.setField(mFragment, "mUnrestrictedData", unrestrictedDataPref); ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend); ReflectionHelpers.setField(mFragment.services, "mPolicyManager", networkPolicyManager); + when(mFragment.getListView()).thenReturn(mock(RecyclerView.class)); ShadowRestrictedLockUtilsInternal.setRestricted(true); doReturn(NetworkPolicyManager.POLICY_NONE).when(networkPolicyManager)