Merge "[DO NOT MERGE] Fix flicker for Data Usage page" into tm-dev
diff --git a/res/xml/data_usage_list.xml b/res/xml/data_usage_list.xml
index 9ea6a91..644fca4 100644
--- a/res/xml/data_usage_list.xml
+++ b/res/xml/data_usage_list.xml
@@ -17,7 +17,8 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
- android:key="usage_amount">
+ android:key="usage_amount"
+ android:title="@string/summary_placeholder">
<com.android.settings.datausage.ChartDataUsagePreference
android:key="chart_data" />
diff --git a/src/com/android/settings/datausage/CycleAdapter.java b/src/com/android/settings/datausage/CycleAdapter.java
index b41b6aa..2af4012 100644
--- a/src/com/android/settings/datausage/CycleAdapter.java
+++ b/src/com/android/settings/datausage/CycleAdapter.java
@@ -21,7 +21,6 @@
import com.android.settingslib.widget.SettingsSpinnerAdapter;
import java.util.List;
-import java.util.Objects;
public class CycleAdapter extends SettingsSpinnerAdapter<CycleAdapter.CycleItem> {
@@ -67,7 +66,7 @@
* Rebuild list based on network data. Always selects the newest item,
* updating the inspection range on chartData.
*/
- public boolean updateCycleList(List<? extends NetworkCycleData> cycleData) {
+ public void updateCycleList(List<? extends NetworkCycleData> cycleData) {
mSpinner.setOnItemSelectedListener(mListener);
// stash away currently selected cycle to try restoring below
final CycleAdapter.CycleItem previousItem = (CycleAdapter.CycleItem)
@@ -83,16 +82,7 @@
if (getCount() > 0) {
final int position = findNearestPosition(previousItem);
mSpinner.setSelection(position);
-
- // only force-update cycle when changed; skipping preserves any
- // user-defined inspection region.
- final CycleAdapter.CycleItem selectedItem = getItem(position);
- if (!Objects.equals(selectedItem, previousItem)) {
- mListener.onItemSelected(null, null, position, 0);
- return false;
- }
}
- return true;
}
/**
diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java
index 4a44a16..9d8fbb1 100644
--- a/src/com/android/settings/datausage/DataUsageList.java
+++ b/src/com/android/settings/datausage/DataUsageList.java
@@ -69,6 +69,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
* Panel showing data usage history across various networks, including options
@@ -111,7 +112,11 @@
private ChartDataUsagePreference mChart;
private List<NetworkCycleChartData> mCycleData;
+ // Caches the cycles for startAppDataUsage usage, which need be cleared when resumed.
private ArrayList<Long> mCycles;
+ // Spinner will keep the selected cycle even after paused, this only keeps the displayed cycle,
+ // which need be cleared when resumed.
+ private CycleAdapter.CycleItem mLastDisplayedCycle;
private UidDetailProvider mUidDetailProvider;
private CycleAdapter mCycleAdapter;
private Preference mUsageAmount;
@@ -199,13 +204,15 @@
mLoadingViewController = new LoadingViewController(
getView().findViewById(R.id.loading_container), getListView());
- mLoadingViewController.showLoadingViewDelayed();
}
@Override
public void onResume() {
super.onResume();
+ mLoadingViewController.showLoadingViewDelayed();
mDataStateListener.start(mSubId);
+ mCycles = null;
+ mLastDisplayedCycle = null;
// kick off loader for network history
// TODO: consider chaining two loaders together instead of reloading
@@ -319,9 +326,46 @@
}
// generate cycle list based on policy and available history
- if (mCycleAdapter.updateCycleList(mCycleData)) {
- updateDetailData();
+ mCycleAdapter.updateCycleList(mCycleData);
+ updateSelectedCycle();
+ }
+
+ /**
+ * Updates the chart and detail data when initial loaded or selected cycle changed.
+ */
+ private void updateSelectedCycle() {
+ // Avoid from updating UI after #onStop.
+ if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
+ return;
}
+
+ // Avoid from updating UI when async query still on-going.
+ // This could happen when a request from #onMobileDataEnabledChange.
+ if (mCycleData == null) {
+ return;
+ }
+
+ final int position = mCycleSpinner.getSelectedItemPosition();
+ if (mCycleAdapter.getCount() == 0 || position < 0) {
+ return;
+ }
+ final CycleAdapter.CycleItem cycle = mCycleAdapter.getItem(position);
+ if (Objects.equals(cycle, mLastDisplayedCycle)) {
+ // Avoid duplicate update to avoid page flash.
+ return;
+ }
+ mLastDisplayedCycle = cycle;
+
+ if (LOGD) {
+ Log.d(TAG, "showing cycle " + cycle + ", [start=" + cycle.start + ", end="
+ + cycle.end + "]");
+ }
+
+ // update chart to show selected cycle, and update detail data
+ // to match updated sweep bounds.
+ mChart.setNetworkCycleData(mCycleData.get(position));
+
+ updateDetailData();
}
/**
@@ -495,33 +539,10 @@
return Math.max(largest, item.total);
}
- private OnItemSelectedListener mCycleListener = new OnItemSelectedListener() {
+ private final OnItemSelectedListener mCycleListener = new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem)
- mCycleSpinner.getSelectedItem();
-
- if (LOGD) {
- Log.d(TAG, "showing cycle " + cycle + ", start=" + cycle.start + ", end="
- + cycle.end + "]");
- }
-
- // Avoid from updating UI after #onStop.
- if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
- return;
- }
-
- // Avoid from updating UI when async query still on-going.
- // This could happen when a request from #onMobileDataEnabledChange.
- if (mCycleData == null) {
- return;
- }
-
- // update chart to show selected cycle, and update detail data
- // to match updated sweep bounds.
- mChart.setNetworkCycleData(mCycleData.get(position));
-
- updateDetailData();
+ updateSelectedCycle();
}
@Override
diff --git a/src/com/android/settings/datausage/SpinnerPreference.java b/src/com/android/settings/datausage/SpinnerPreference.java
index c4b7a4e..c6b5f9f 100644
--- a/src/com/android/settings/datausage/SpinnerPreference.java
+++ b/src/com/android/settings/datausage/SpinnerPreference.java
@@ -14,6 +14,7 @@
package com.android.settings.datausage;
+import android.annotation.Nullable;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
@@ -28,6 +29,7 @@
public class SpinnerPreference extends Preference implements CycleAdapter.SpinnerInterface {
private CycleAdapter mAdapter;
+ @Nullable
private AdapterView.OnItemSelectedListener mListener;
private Object mCurrentObject;
private int mPosition;
@@ -88,19 +90,24 @@
view.findViewById(R.id.cycles_spinner).performClick();
}
- private final AdapterView.OnItemSelectedListener mOnSelectedListener
- = new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- if (mPosition == position) return;
- mPosition = position;
- mCurrentObject = mAdapter.getItem(position);
- mListener.onItemSelected(parent, view, position, id);
- }
+ private final AdapterView.OnItemSelectedListener mOnSelectedListener =
+ new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(
+ AdapterView<?> parent, View view, int position, long id) {
+ if (mPosition == position) return;
+ mPosition = position;
+ mCurrentObject = mAdapter.getItem(position);
+ if (mListener != null) {
+ mListener.onItemSelected(parent, view, position, id);
+ }
+ }
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- mListener.onNothingSelected(parent);
- }
- };
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ if (mListener != null) {
+ mListener.onNothingSelected(parent);
+ }
+ }
+ };
}
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
index e4f5b1f..a13cf6c 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
@@ -94,6 +94,7 @@
mMobileDataEnabledListener);
ReflectionHelpers.setField(mDataUsageList, "services", mNetworkServices);
doReturn(mLoaderManager).when(mDataUsageList).getLoaderManager();
+ mDataUsageList.mLoadingViewController = mock(LoadingViewController.class);
}
@Test
@@ -207,8 +208,6 @@
@Test
public void onLoadFinished_networkCycleDataCallback_shouldShowCycleSpinner() {
- final LoadingViewController loadingViewController = mock(LoadingViewController.class);
- mDataUsageList.mLoadingViewController = loadingViewController;
final Spinner spinner = getSpinner(getHeader());
spinner.setVisibility(View.INVISIBLE);
mDataUsageList.mCycleSpinner = spinner;