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
This commit is contained in:
Chaohui Wang
2022-05-27 00:20:45 +08:00
parent f6ea9c99b3
commit c2dacf1b75
2 changed files with 34 additions and 0 deletions

View File

@@ -40,6 +40,8 @@ import androidx.loader.content.Loader;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener; import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceCategory;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.AppInfoBase;
@@ -105,6 +107,7 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
private Context mContext; private Context mContext;
private ArrayList<Long> mCycles; private ArrayList<Long> mCycles;
private long mSelectedCycle; private long mSelectedCycle;
private boolean mIsLoading;
@Override @Override
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
@@ -226,6 +229,16 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
@Override @Override
public void onResume() { public void onResume() {
super.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) { if (mDataSaverBackend != null) {
mDataSaverBackend.addListener(this); 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) { private void updatePrefs(boolean restrictBackground, boolean unrestrictData) {
setBackPreferenceListAnimatorIfLoaded();
final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfMeteredDataRestricted( final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfMeteredDataRestricted(
mContext, mPackageName, UserHandle.getUserId(mAppItem.key)); mContext, mPackageName, UserHandle.getUserId(mAppItem.key));
if (mRestrictBackground != null) { if (mRestrictBackground != null) {
@@ -448,6 +479,7 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
} else { } else {
bindData(0 /* position */); bindData(0 /* position */);
} }
mIsLoading = false;
} }
@Override @Override

View File

@@ -48,6 +48,7 @@ import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.AppInfoBase;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
@@ -240,6 +241,7 @@ public class AppDataUsageTest {
ReflectionHelpers.setField(mFragment, "mUnrestrictedData", unrestrictedDataPref); ReflectionHelpers.setField(mFragment, "mUnrestrictedData", unrestrictedDataPref);
ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend); ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend);
ReflectionHelpers.setField(mFragment.services, "mPolicyManager", networkPolicyManager); ReflectionHelpers.setField(mFragment.services, "mPolicyManager", networkPolicyManager);
when(mFragment.getListView()).thenReturn(mock(RecyclerView.class));
ShadowRestrictedLockUtilsInternal.setRestricted(true); ShadowRestrictedLockUtilsInternal.setRestricted(true);
doReturn(NetworkPolicyManager.POLICY_NONE).when(networkPolicyManager) doReturn(NetworkPolicyManager.POLICY_NONE).when(networkPolicyManager)