Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 98fa9deb authored by Chaohui Wang's avatar Chaohui Wang Committed by Android (Google) Code Review
Browse files

Merge "[DO NOT MERGE] Fix flicker for Data Usage page" into tm-dev

parents a571dd99 5a2f5ecf
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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" />
+1 −11
Original line number Diff line number Diff line
@@ -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<CycleAdapter.CycleItem> {

@@ -67,7 +66,7 @@ public class CycleAdapter extends SettingsSpinnerAdapter<CycleAdapter.CycleItem>
     * 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 @@ public class CycleAdapter extends SettingsSpinnerAdapter<CycleAdapter.CycleItem>
        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;
    }

    /**
+49 −28
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ import com.android.settingslib.net.UidDetailProvider;
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 @@ public class DataUsageList extends DataUsageBaseFragment

    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 @@ 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
@@ -319,9 +326,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();
    }

    /**
@@ -495,33 +539,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
+22 −15
Original line number Diff line number Diff line
@@ -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() {
    private final AdapterView.OnItemSelectedListener mOnSelectedListener =
            new AdapterView.OnItemSelectedListener() {
                @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                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) {
                    if (mListener != null) {
                        mListener.onNothingSelected(parent);
                    }
                }
            };
}
+1 −2
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ public class DataUsageListTest {
                mMobileDataEnabledListener);
        ReflectionHelpers.setField(mDataUsageList, "services", mNetworkServices);
        doReturn(mLoaderManager).when(mDataUsageList).getLoaderManager();
        mDataUsageList.mLoadingViewController = mock(LoadingViewController.class);
    }

    @Test
@@ -207,8 +208,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;