From 52b723beefe0e70c46e6c0930c47c57e54bc2c1f Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Sat, 22 Apr 2023 08:35:45 +0800 Subject: [PATCH 1/3] Revert "[Settings] Adjusting the control of display sequence (part 2)" This reverts commit 6b379cd7cf4c3b648a24313cd11821d7c08da858. Bug: 277162513 Test: Manual Change-Id: Iea61c06d328626a96c13c4c9f8a11f8329401b35 --- .../datausage/ChartDataUsagePreference.java | 15 ++++++++------- .../android/settings/datausage/DataUsageList.java | 3 --- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/com/android/settings/datausage/ChartDataUsagePreference.java b/src/com/android/settings/datausage/ChartDataUsagePreference.java index dedeb7b5d16..286d9e5195d 100644 --- a/src/com/android/settings/datausage/ChartDataUsagePreference.java +++ b/src/com/android/settings/datausage/ChartDataUsagePreference.java @@ -73,20 +73,21 @@ public class ChartDataUsagePreference extends Preference { } private void onUpdateView() { - if ((mUsageView == null) || (mNetworkCycleChartData == null)) { + UsageView chart = mUsageView; + if ((chart == null) || (mNetworkCycleChartData == null)) { return; } final int top = getTop(); - mUsageView.clearPaths(); - mUsageView.configureGraph(toInt(mEnd - mStart), top); - calcPoints(mUsageView, mNetworkCycleChartData.getUsageBuckets()); - setupContentDescription(mUsageView, mNetworkCycleChartData.getUsageBuckets()); - mUsageView.setBottomLabels(new CharSequence[] { + chart.clearPaths(); + chart.configureGraph(toInt(mEnd - mStart), top); + calcPoints(chart, mNetworkCycleChartData.getUsageBuckets()); + setupContentDescription(chart, mNetworkCycleChartData.getUsageBuckets()); + chart.setBottomLabels(new CharSequence[] { Utils.formatDateRange(getContext(), mStart, mStart), Utils.formatDateRange(getContext(), mEnd, mEnd), }); - bindNetworkPolicy(mUsageView, mPolicy, top); + bindNetworkPolicy(chart, mPolicy, top); } public int getTop() { diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java index c0ccb7638dc..eea1b00e047 100644 --- a/src/com/android/settings/datausage/DataUsageList.java +++ b/src/com/android/settings/datausage/DataUsageList.java @@ -345,9 +345,6 @@ public class DataUsageList extends DataUsageBaseFragment */ @VisibleForTesting void updatePolicy() { - if (mHeader == null) { - return; - } final NetworkPolicy policy = services.mPolicyEditor.getPolicy(mTemplate); final View configureButton = mHeader.findViewById(R.id.filter_settings); //SUB SELECT From f46b33bbc4c06c69165fafd4219d57bd9200d0e4 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Sat, 22 Apr 2023 08:35:55 +0800 Subject: [PATCH 2/3] Revert "[DataUsage] Adjusting the control of display sequence" This reverts commit b8491032d75a6c021b75f769d37d2849981476f8. Bug: 277162513 Test: Manual Test: Unit test Change-Id: I5a84a9b1a99b1da4c18d786a6dff062b53cd46c6 --- .../datausage/ChartDataUsagePreference.java | 46 +++++-------------- .../settings/datausage/DataUsageList.java | 29 ++++-------- .../ChartDataUsagePreferenceTest.java | 40 ++++++---------- .../settings/datausage/DataUsageListTest.java | 45 +++++++++--------- 4 files changed, 57 insertions(+), 103 deletions(-) diff --git a/src/com/android/settings/datausage/ChartDataUsagePreference.java b/src/com/android/settings/datausage/ChartDataUsagePreference.java index 286d9e5195d..12fb03b6258 100644 --- a/src/com/android/settings/datausage/ChartDataUsagePreference.java +++ b/src/com/android/settings/datausage/ChartDataUsagePreference.java @@ -48,8 +48,8 @@ public class ChartDataUsagePreference extends Preference { // Set to half a meg for now. private static final long RESOLUTION = DataUnit.MEBIBYTES.toBytes(1) / 2; - private int mWarningColor; - private int mLimitColor; + private final int mWarningColor; + private final int mLimitColor; private Resources mResources; private NetworkPolicy mPolicy; @@ -58,25 +58,24 @@ public class ChartDataUsagePreference extends Preference { private NetworkCycleChartData mNetworkCycleChartData; private int mSecondaryColor; private int mSeriesColor; - private UsageView mUsageView; - private boolean mSuspendUiUpdate; // Suppress UI updates to save some CPU time. public ChartDataUsagePreference(Context context, AttributeSet attrs) { super(context, attrs); + mResources = context.getResources(); setSelectable(false); + mLimitColor = Utils.getColorAttrDefaultColor(context, android.R.attr.colorError); + mWarningColor = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary); + setLayoutResource(R.layout.data_usage_graph); } @Override public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); - mUsageView = (UsageView) holder.findViewById(R.id.data_usage); - } - - private void onUpdateView() { - UsageView chart = mUsageView; - if ((chart == null) || (mNetworkCycleChartData == null)) { + final UsageView chart = (UsageView) holder.findViewById(R.id.data_usage); + if (mNetworkCycleChartData == null) { return; } + final int top = getTop(); chart.clearPaths(); chart.configureGraph(toInt(mEnd - mStart), top); @@ -292,16 +291,9 @@ public class ChartDataUsagePreference extends Preference { return new SpannableStringBuilder().append(label, new ForegroundColorSpan(mLimitColor), 0); } - public void onPreparingChartData() { - mSuspendUiUpdate = true; - } - public void setNetworkPolicy(NetworkPolicy policy) { mPolicy = policy; - if ((!mSuspendUiUpdate) && (mResources != null)) { - onUpdateView(); - notifyChanged(); - } + notifyChanged(); } public long getInspectStart() { @@ -313,31 +305,15 @@ public class ChartDataUsagePreference extends Preference { } public void setNetworkCycleData(NetworkCycleChartData data) { - if (data == null) { - return; - } mNetworkCycleChartData = data; mStart = data.getStartTime(); mEnd = data.getEndTime(); - if (mResources == null) { - Context context = getContext(); - mResources = context.getResources(); - mLimitColor = Utils.getColorAttrDefaultColor(context, android.R.attr.colorError); - mWarningColor = Utils.getColorAttrDefaultColor(context, - android.R.attr.textColorSecondary); - setLayoutResource(R.layout.data_usage_graph); - } - onUpdateView(); notifyChanged(); - mSuspendUiUpdate = false; } public void setColors(int seriesColor, int secondaryColor) { mSeriesColor = seriesColor; mSecondaryColor = secondaryColor; - if ((!mSuspendUiUpdate) && (mResources != null)) { - onUpdateView(); - notifyChanged(); - } + notifyChanged(); } } diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java index eea1b00e047..ef25f13c1b6 100644 --- a/src/com/android/settings/datausage/DataUsageList.java +++ b/src/com/android/settings/datausage/DataUsageList.java @@ -172,20 +172,7 @@ public class DataUsageList extends DataUsageBaseFragment public void onViewCreated(View v, Bundle savedInstanceState) { super.onViewCreated(v, savedInstanceState); - // Show loading - mLoadingViewController = new LoadingViewController( - v.findViewById(R.id.loading_container), getListView()); - mLoadingViewController.showLoadingViewDelayed(); - } - - private void onEndOfLoading() { - if (mHeader != null) { - return; - } mHeader = setPinnedHeaderView(R.layout.apps_filter_spinner); - - mCycleSpinner = mHeader.findViewById(R.id.filter_spinner); - mHeader.findViewById(R.id.filter_settings).setOnClickListener(btn -> { final Bundle args = new Bundle(); args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mTemplate); @@ -196,6 +183,8 @@ public class DataUsageList extends DataUsageBaseFragment .setArguments(args) .launch(); }); + mCycleSpinner = mHeader.findViewById(R.id.filter_spinner); + mCycleSpinner.setVisibility(View.GONE); mCycleAdapter = new CycleAdapter(mCycleSpinner.getContext(), new SpinnerInterface() { @Override public void setAdapter(CycleAdapter cycleAdapter) { @@ -227,6 +216,10 @@ public class DataUsageList extends DataUsageBaseFragment super.sendAccessibilityEvent(host, eventType); } }); + + mLoadingViewController = new LoadingViewController( + getView().findViewById(R.id.loading_container), getListView()); + mLoadingViewController.showLoadingViewDelayed(); } @Override @@ -234,10 +227,6 @@ public class DataUsageList extends DataUsageBaseFragment super.onResume(); mDataStateListener.start(mSubId); - if (mChart != null) { - mChart.onPreparingChartData(); - } - // kick off loader for network history // TODO: consider chaining two loaders together instead of reloading // network history when showing app detail. @@ -599,13 +588,11 @@ public class DataUsageList extends DataUsageBaseFragment @Override public void onLoadFinished(Loader> loader, List data) { - onEndOfLoading(); - if (mLoadingViewController != null) { - mLoadingViewController.showContent(false /* animate */); - } + mLoadingViewController.showContent(false /* animate */); mCycleData = data; // calculate policy cycles based on available data updatePolicy(); + mCycleSpinner.setVisibility(View.VISIBLE); } @Override diff --git a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java index 3be652dbdde..aab67be1de9 100644 --- a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java +++ b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java @@ -17,10 +17,7 @@ package com.android.settings.datausage; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -166,32 +163,23 @@ public class ChartDataUsagePreferenceTest { @Test public void notifyChange_nonEmptyDataUsage_shouldHaveSingleContentDescription() { - final ArgumentCaptor contentCaptor = - ArgumentCaptor.forClass(CharSequence.class); - final UsageView chart = mock(UsageView.class); - doReturn(chart).when(mHolder).findViewById(R.id.data_usage); - final TextView labelTop = mock(TextView.class); - doReturn(labelTop).when(mHolder).findViewById(R.id.label_top); - final TextView labelMiddle = mock(TextView.class); - doReturn(labelMiddle).when(mHolder).findViewById(R.id.label_middle); - final TextView labelBottom = mock(TextView.class); - doReturn(labelBottom).when(mHolder).findViewById(R.id.label_bottom); - final TextView labelStart = mock(TextView.class); - doReturn(labelStart).when(mHolder).findViewById(R.id.label_start); - final TextView labelEnd = mock(TextView.class); - doReturn(labelEnd).when(mHolder).findViewById(R.id.label_end); + final UsageView chart = (UsageView) mHolder.findViewById(R.id.data_usage); + final TextView labelTop = (TextView) mHolder.findViewById(R.id.label_top); + final TextView labelMiddle = (TextView) mHolder.findViewById(R.id.label_middle); + final TextView labelBottom = (TextView) mHolder.findViewById(R.id.label_bottom); + final TextView labelStart = (TextView) mHolder.findViewById(R.id.label_start); + final TextView labelEnd = (TextView) mHolder.findViewById(R.id.label_end); createTestNetworkData(); - - mPreference.onBindViewHolder(mHolder); mPreference.setNetworkCycleData(mNetworkCycleChartData); - verify(chart).setContentDescription(contentCaptor.capture()); - assertThat(contentCaptor.getValue()).isNotNull(); - verify(labelTop, never()).setContentDescription(any()); - verify(labelMiddle, never()).setContentDescription(any()); - verify(labelBottom, never()).setContentDescription(any()); - verify(labelStart, never()).setContentDescription(any()); - verify(labelEnd, never()).setContentDescription(any()); + mPreference.onBindViewHolder(mHolder); + + assertThat(chart.getContentDescription()).isNotNull(); + assertThat(labelTop.getContentDescription()).isNull(); + assertThat(labelMiddle.getContentDescription()).isNull(); + assertThat(labelBottom.getContentDescription()).isNull(); + assertThat(labelStart.getContentDescription()).isNull(); + assertThat(labelEnd.getContentDescription()).isNull(); } @Test diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java index f7db0d56db4..dc728ee2a31 100644 --- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java +++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java @@ -222,23 +222,32 @@ public class DataUsageListTest { } @Test - public void onViewCreated_shouldNotSetCycleSpinner() { - View view = constructRootView(); + public void onViewCreated_shouldHideCycleSpinner() { + final View view = new View(mActivity); + final View header = getHeader(); + final Spinner spinner = getSpinner(header); + spinner.setVisibility(View.VISIBLE); + doReturn(header).when(mDataUsageList).setPinnedHeaderView(anyInt()); + doReturn(view).when(mDataUsageList).getView(); mDataUsageList.onViewCreated(view, null); - assertThat(getSpinner(view)).isNull(); + assertThat(spinner.getVisibility()).isEqualTo(View.GONE); } @Test - public void onLoadFinished_networkCycleDataCallback_shouldSetCycleSpinner() { - final View view = constructRootView(); + 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; + assertThat(spinner.getVisibility()).isEqualTo(View.INVISIBLE); doNothing().when(mDataUsageList).updatePolicy(); - doReturn(setupHeaderView(view)).when(mDataUsageList).setPinnedHeaderView(anyInt()); mDataUsageList.mNetworkCycleDataCallbacks.onLoadFinished(null, null); - assertThat(getSpinner(view)).isNotNull(); + assertThat(spinner.getVisibility()).isEqualTo(View.VISIBLE); } @Test @@ -249,25 +258,19 @@ public class DataUsageListTest { verify(mLoaderManager).destroyLoader(DataUsageList.LOADER_SUMMARY); } - private View constructRootView() { - View rootView = LayoutInflater.from(mActivity) + private View getHeader() { + final View rootView = LayoutInflater.from(mActivity) .inflate(R.layout.preference_list_fragment, null, false); - return rootView; - } - - private View setupHeaderView(View rootView) { - final FrameLayout pinnedHeader = (FrameLayout) rootView.findViewById(R.id.pinned_header); + final FrameLayout pinnedHeader = rootView.findViewById(R.id.pinned_header); final View header = mActivity.getLayoutInflater() - .inflate(R.layout.apps_filter_spinner, pinnedHeader, true); + .inflate(R.layout.apps_filter_spinner, pinnedHeader, false); + return header; } - private Spinner getSpinner(View rootView) { - final FrameLayout pinnedHeader = (FrameLayout) rootView.findViewById(R.id.pinned_header); - if (pinnedHeader == null) { - return null; - } - return pinnedHeader.findViewById(R.id.filter_spinner); + private Spinner getSpinner(View header) { + final Spinner spinner = header.findViewById(R.id.filter_spinner); + return spinner; } @Implements(DataUsageBaseFragment.class) From 8397287f877fb7982d35a42d5f618e890dc679b4 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Wed, 11 May 2022 11:42:11 +0800 Subject: [PATCH 3/3] Fix flicker for Data Usage page Both "Mobile data usage" & "Non-carrier data usage". By, 1. Use summary placeholder for usage amount to avoid shift 2. Before fix CycleListener's onItemSelected() is called multiple times, cause the app list to flash, let DataUsageList to handle the dedup logic to better handling. 3. Before fix if return from App Usage page, no loading view is displayed (only first enter has it), move this to onResume() to fix. 4. Before fix the cycles passed to App Usage page is cached (even when the cycles are changed), clear the cache when onResume() to fix. 5. Listener in SpinnerPreference could be null, add safety guard to it. Cherry-pick from Change-Id: I95e544c46333496f4f30ed77dafa4779b4d66019 Fix: 277162513 Test: manual visual test Test: Unit test Change-Id: I50fb79aa3c888651a79fd1d030da554bebb6a660 --- res/xml/data_usage_list.xml | 3 +- .../settings/datausage/CycleAdapter.java | 12 +-- .../settings/datausage/DataUsageList.java | 77 ++++++++++++------- .../settings/datausage/SpinnerPreference.java | 35 +++++---- .../settings/datausage/DataUsageListTest.java | 3 +- 5 files changed, 74 insertions(+), 56 deletions(-) diff --git a/res/xml/data_usage_list.xml b/res/xml/data_usage_list.xml index 9ea6a914a77..644fca4faf7 100644 --- a/res/xml/data_usage_list.xml +++ b/res/xml/data_usage_list.xml @@ -17,7 +17,8 @@ + android:key="usage_amount" + android:title="@string/summary_placeholder"> diff --git a/src/com/android/settings/datausage/CycleAdapter.java b/src/com/android/settings/datausage/CycleAdapter.java index b41b6aad91b..2af40120864 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.net.NetworkCycleData; import com.android.settingslib.widget.SettingsSpinnerAdapter; import java.util.List; -import java.util.Objects; public class CycleAdapter extends SettingsSpinnerAdapter { @@ -67,7 +66,7 @@ public class CycleAdapter extends SettingsSpinnerAdapter * Rebuild list based on network data. Always selects the newest item, * updating the inspection range on chartData. */ - public boolean updateCycleList(List cycleData) { + public void updateCycleList(List cycleData) { mSpinner.setOnItemSelectedListener(mListener); // stash away currently selected cycle to try restoring below final CycleAdapter.CycleItem previousItem = (CycleAdapter.CycleItem) @@ -83,16 +82,7 @@ public class CycleAdapter extends SettingsSpinnerAdapter 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 ef25f13c1b6..1855c2e44e9 100644 --- a/src/com/android/settings/datausage/DataUsageList.java +++ b/src/com/android/settings/datausage/DataUsageList.java @@ -75,6 +75,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Optional; /** @@ -118,7 +119,11 @@ public class DataUsageList extends DataUsageBaseFragment private ChartDataUsagePreference mChart; private List mCycleData; + // Caches the cycles for startAppDataUsage usage, which need be cleared when resumed. private ArrayList 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; @@ -219,13 +224,15 @@ public class DataUsageList extends DataUsageBaseFragment 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 @@ -348,9 +355,46 @@ public class DataUsageList extends DataUsageBaseFragment } // 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(); } /** @@ -540,33 +584,10 @@ public class DataUsageList extends DataUsageBaseFragment 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 c4b7a4e18da..c6b5f9f8ecc 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 @@ import com.android.settings.R; 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 @@ public class SpinnerPreference extends Preference implements CycleAdapter.Spinne 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 dc728ee2a31..951829b1738 100644 --- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java +++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java @@ -103,6 +103,7 @@ public class DataUsageListTest { mMobileDataEnabledListener); ReflectionHelpers.setField(mDataUsageList, "services", mNetworkServices); doReturn(mLoaderManager).when(mDataUsageList).getLoaderManager(); + mDataUsageList.mLoadingViewController = mock(LoadingViewController.class); } @Test @@ -237,8 +238,6 @@ public class DataUsageListTest { @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;