Reduce jank around loading view when opening data usage UI
Change-Id: I3d23d8160b046de8fe125ba0697b7b3d7786453c Fix: 28181319 Test: robotests
This commit is contained in:
@@ -49,6 +49,7 @@ import com.android.settings.applications.LayoutPreference;
|
|||||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||||
import com.android.settings.core.instrumentation.Instrumentable;
|
import com.android.settings.core.instrumentation.Instrumentable;
|
||||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||||
|
import com.android.settings.widget.LoadingViewController;
|
||||||
import com.android.settingslib.CustomDialogPreference;
|
import com.android.settingslib.CustomDialogPreference;
|
||||||
import com.android.settingslib.CustomEditTextPreference;
|
import com.android.settingslib.CustomEditTextPreference;
|
||||||
import com.android.settingslib.HelpUtils;
|
import com.android.settingslib.HelpUtils;
|
||||||
@@ -240,14 +241,11 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
|
|||||||
unregisterObserverIfNeeded();
|
unregisterObserverIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showLoadingWhenEmpty() {
|
|
||||||
View loading = getView().findViewById(R.id.loading_container);
|
|
||||||
setEmptyView(loading);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLoading(boolean loading, boolean animate) {
|
public void setLoading(boolean loading, boolean animate) {
|
||||||
View loading_container = getView().findViewById(R.id.loading_container);
|
View loadingContainer = getView().findViewById(R.id.loading_container);
|
||||||
Utils.handleLoadingContainer(loading_container, getListView(), !loading, animate);
|
LoadingViewController.handleLoadingContainer(loadingContainer, getListView(),
|
||||||
|
!loading /* done */,
|
||||||
|
animate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerObserverIfNeeded() {
|
public void registerObserverIfNeeded() {
|
||||||
|
@@ -949,43 +949,6 @@ public final class Utils extends com.android.settingslib.Utils {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move this out of Utils to a mixin or a controller or a helper class.
|
|
||||||
@Deprecated
|
|
||||||
public static void handleLoadingContainer(View loading, View doneLoading, boolean done,
|
|
||||||
boolean animate) {
|
|
||||||
setViewShown(loading, !done, animate);
|
|
||||||
setViewShown(doneLoading, done, animate);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setViewShown(final View view, boolean shown, boolean animate) {
|
|
||||||
if (animate) {
|
|
||||||
Animation animation = AnimationUtils.loadAnimation(view.getContext(),
|
|
||||||
shown ? android.R.anim.fade_in : android.R.anim.fade_out);
|
|
||||||
if (shown) {
|
|
||||||
view.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
animation.setAnimationListener(new AnimationListener() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationStart(Animation animation) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAnimationRepeat(Animation animation) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animation animation) {
|
|
||||||
view.setVisibility(View.INVISIBLE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
view.startAnimation(animation);
|
|
||||||
} else {
|
|
||||||
view.clearAnimation();
|
|
||||||
view.setVisibility(shown ? View.VISIBLE : View.INVISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the application info of the currently installed MDM package.
|
* Returns the application info of the currently installed MDM package.
|
||||||
*/
|
*/
|
||||||
|
@@ -81,6 +81,7 @@ import com.android.settings.notification.AppNotificationSettings;
|
|||||||
import com.android.settings.notification.ConfigureNotificationSettings;
|
import com.android.settings.notification.ConfigureNotificationSettings;
|
||||||
import com.android.settings.notification.NotificationBackend;
|
import com.android.settings.notification.NotificationBackend;
|
||||||
import com.android.settings.notification.NotificationBackend.AppRow;
|
import com.android.settings.notification.NotificationBackend.AppRow;
|
||||||
|
import com.android.settings.widget.LoadingViewController;
|
||||||
import com.android.settingslib.HelpUtils;
|
import com.android.settingslib.HelpUtils;
|
||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||||
@@ -848,6 +849,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
|||||||
private final AppStateBaseBridge mExtraInfoBridge;
|
private final AppStateBaseBridge mExtraInfoBridge;
|
||||||
private final Handler mBgHandler;
|
private final Handler mBgHandler;
|
||||||
private final Handler mFgHandler;
|
private final Handler mFgHandler;
|
||||||
|
private final LoadingViewController mLoadingViewController;
|
||||||
|
|
||||||
private int mFilterMode;
|
private int mFilterMode;
|
||||||
private ArrayList<ApplicationsState.AppEntry> mBaseEntries;
|
private ArrayList<ApplicationsState.AppEntry> mBaseEntries;
|
||||||
@@ -893,12 +895,6 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private Runnable mShowLoadingContainerRunnable = new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
Utils.handleLoadingContainer(mManageApplications.mLoadingContainer,
|
|
||||||
mManageApplications.mListContainer, false /* done */, false /* animate */);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public ApplicationsAdapter(ApplicationsState state, ManageApplications manageApplications,
|
public ApplicationsAdapter(ApplicationsState state, ManageApplications manageApplications,
|
||||||
int filterMode) {
|
int filterMode) {
|
||||||
@@ -907,6 +903,10 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
|||||||
mBgHandler = new Handler(mState.getBackgroundLooper());
|
mBgHandler = new Handler(mState.getBackgroundLooper());
|
||||||
mSession = state.newSession(this);
|
mSession = state.newSession(this);
|
||||||
mManageApplications = manageApplications;
|
mManageApplications = manageApplications;
|
||||||
|
mLoadingViewController = new LoadingViewController(
|
||||||
|
mManageApplications.mLoadingContainer,
|
||||||
|
mManageApplications.mListContainer
|
||||||
|
);
|
||||||
mContext = manageApplications.getActivity();
|
mContext = manageApplications.getActivity();
|
||||||
mPm = mContext.getPackageManager();
|
mPm = mContext.getPackageManager();
|
||||||
mFilterMode = filterMode;
|
mFilterMode = filterMode;
|
||||||
@@ -1108,11 +1108,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
|||||||
|
|
||||||
if (mSession.getAllApps().size() != 0
|
if (mSession.getAllApps().size() != 0
|
||||||
&& mManageApplications.mListContainer.getVisibility() != View.VISIBLE) {
|
&& mManageApplications.mListContainer.getVisibility() != View.VISIBLE) {
|
||||||
// Cancel any pending task to show the loading animation and show the list of
|
mLoadingViewController.showContent(true /* animate */);
|
||||||
// apps directly.
|
|
||||||
mFgHandler.removeCallbacks(mShowLoadingContainerRunnable);
|
|
||||||
Utils.handleLoadingContainer(mManageApplications.mLoadingContainer,
|
|
||||||
mManageApplications.mListContainer, true, true);
|
|
||||||
}
|
}
|
||||||
if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
|
if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
|
||||||
// No enabled or disabled filters for usage access.
|
// No enabled or disabled filters for usage access.
|
||||||
@@ -1166,11 +1162,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
|||||||
void updateLoading() {
|
void updateLoading() {
|
||||||
final boolean appLoaded = mHasReceivedLoadEntries && mSession.getAllApps().size() != 0;
|
final boolean appLoaded = mHasReceivedLoadEntries && mSession.getAllApps().size() != 0;
|
||||||
if (appLoaded) {
|
if (appLoaded) {
|
||||||
Utils.handleLoadingContainer(mManageApplications.mLoadingContainer,
|
mLoadingViewController.showContent(false /* animate */);
|
||||||
mManageApplications.mListContainer, true /* done */, false /* animate */);
|
|
||||||
} else {
|
} else {
|
||||||
mFgHandler.postDelayed(
|
mLoadingViewController.showLoadingViewDelayed();
|
||||||
mShowLoadingContainerRunnable, DELAY_SHOW_LOADING_CONTAINER_THRESHOLD_MS);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.applications;
|
package com.android.settings.applications;
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -27,7 +26,7 @@ import android.view.ViewGroup;
|
|||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SettingsPreferenceFragment;
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
import com.android.settings.Utils;
|
import com.android.settings.widget.LoadingViewController;
|
||||||
|
|
||||||
public class RunningServices extends SettingsPreferenceFragment {
|
public class RunningServices extends SettingsPreferenceFragment {
|
||||||
|
|
||||||
@@ -37,6 +36,7 @@ public class RunningServices extends SettingsPreferenceFragment {
|
|||||||
private RunningProcessesView mRunningProcessesView;
|
private RunningProcessesView mRunningProcessesView;
|
||||||
private Menu mOptionsMenu;
|
private Menu mOptionsMenu;
|
||||||
private View mLoadingContainer;
|
private View mLoadingContainer;
|
||||||
|
private LoadingViewController mLoadingViewController;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -47,12 +47,13 @@ public class RunningServices extends SettingsPreferenceFragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View rootView = inflater.inflate(R.layout.manage_applications_running, null);
|
View rootView = inflater.inflate(R.layout.manage_applications_running, null);
|
||||||
mRunningProcessesView = (RunningProcessesView) rootView.findViewById(
|
mRunningProcessesView = rootView.findViewById(R.id.running_processes);
|
||||||
R.id.running_processes);
|
|
||||||
mRunningProcessesView.doCreate();
|
mRunningProcessesView.doCreate();
|
||||||
mLoadingContainer = rootView.findViewById(R.id.loading_container);
|
mLoadingContainer = rootView.findViewById(R.id.loading_container);
|
||||||
|
mLoadingViewController = new LoadingViewController(
|
||||||
|
mLoadingContainer, mRunningProcessesView);
|
||||||
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
@@ -71,7 +72,7 @@ public class RunningServices extends SettingsPreferenceFragment {
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
boolean haveData = mRunningProcessesView.doResume(this, mRunningProcessesAvail);
|
boolean haveData = mRunningProcessesView.doResume(this, mRunningProcessesAvail);
|
||||||
Utils.handleLoadingContainer(mLoadingContainer, mRunningProcessesView, haveData, false);
|
mLoadingViewController.handleLoadingContainer(haveData /* done */, false /* animate */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -115,7 +116,7 @@ public class RunningServices extends SettingsPreferenceFragment {
|
|||||||
private final Runnable mRunningProcessesAvail = new Runnable() {
|
private final Runnable mRunningProcessesAvail = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Utils.handleLoadingContainer(mLoadingContainer, mRunningProcessesView, true, true);
|
mLoadingViewController.showContent(true /* animate */);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -50,6 +50,7 @@ import android.widget.Spinner;
|
|||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.datausage.CycleAdapter.SpinnerInterface;
|
import com.android.settings.datausage.CycleAdapter.SpinnerInterface;
|
||||||
|
import com.android.settings.widget.LoadingViewController;
|
||||||
import com.android.settingslib.AppItem;
|
import com.android.settingslib.AppItem;
|
||||||
import com.android.settingslib.net.ChartData;
|
import com.android.settingslib.net.ChartData;
|
||||||
import com.android.settingslib.net.ChartDataLoader;
|
import com.android.settingslib.net.ChartDataLoader;
|
||||||
@@ -96,13 +97,13 @@ public class DataUsageList extends DataUsageBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private INetworkStatsSession mStatsSession;
|
private INetworkStatsSession mStatsSession;
|
||||||
|
|
||||||
private ChartDataUsagePreference mChart;
|
private ChartDataUsagePreference mChart;
|
||||||
|
|
||||||
private NetworkTemplate mTemplate;
|
private NetworkTemplate mTemplate;
|
||||||
private int mSubId;
|
private int mSubId;
|
||||||
private ChartData mChartData;
|
private ChartData mChartData;
|
||||||
|
|
||||||
|
private LoadingViewController mLoadingViewController;
|
||||||
private UidDetailProvider mUidDetailProvider;
|
private UidDetailProvider mUidDetailProvider;
|
||||||
private CycleAdapter mCycleAdapter;
|
private CycleAdapter mCycleAdapter;
|
||||||
private Spinner mCycleSpinner;
|
private Spinner mCycleSpinner;
|
||||||
@@ -110,6 +111,7 @@ public class DataUsageList extends DataUsageBase {
|
|||||||
private PreferenceGroup mApps;
|
private PreferenceGroup mApps;
|
||||||
private View mHeader;
|
private View mHeader;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMetricsCategory() {
|
public int getMetricsCategory() {
|
||||||
return MetricsEvent.DATA_USAGE_LIST;
|
return MetricsEvent.DATA_USAGE_LIST;
|
||||||
@@ -176,7 +178,10 @@ public class DataUsageList extends DataUsageBase {
|
|||||||
mCycleSpinner.setSelection(position);
|
mCycleSpinner.setSelection(position);
|
||||||
}
|
}
|
||||||
}, mCycleListener, true);
|
}, mCycleListener, true);
|
||||||
setLoading(true, false);
|
|
||||||
|
mLoadingViewController = new LoadingViewController(
|
||||||
|
getView().findViewById(R.id.loading_container), getListView());
|
||||||
|
mLoadingViewController.showLoadingViewDelayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -523,7 +528,7 @@ public class DataUsageList extends DataUsageBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
|
public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
|
||||||
setLoading(false, true);
|
mLoadingViewController.showContent(false /* animate */);
|
||||||
mChartData = data;
|
mChartData = data;
|
||||||
mChart.setNetworkStats(mChartData.network);
|
mChart.setNetworkStats(mChartData.network);
|
||||||
|
|
||||||
|
106
src/com/android/settings/widget/LoadingViewController.java
Normal file
106
src/com/android/settings/widget/LoadingViewController.java
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.widget;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.animation.Animation;
|
||||||
|
import android.view.animation.AnimationUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class that manages show/hide loading spinner.
|
||||||
|
*/
|
||||||
|
public class LoadingViewController {
|
||||||
|
|
||||||
|
private static final long DELAY_SHOW_LOADING_CONTAINER_THRESHOLD_MS = 100L;
|
||||||
|
|
||||||
|
public final Handler mFgHandler;
|
||||||
|
public final View mLoadingView;
|
||||||
|
public final View mContentView;
|
||||||
|
|
||||||
|
public LoadingViewController(View loadingView, View contentView) {
|
||||||
|
mLoadingView = loadingView;
|
||||||
|
mContentView = contentView;
|
||||||
|
mFgHandler = new Handler(Looper.getMainLooper());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Runnable mShowLoadingContainerRunnable = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
handleLoadingContainer(false /* done */, false /* animate */);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void showContent(boolean animate) {
|
||||||
|
// Cancel any pending task to show the loading animation and show the list of
|
||||||
|
// apps directly.
|
||||||
|
mFgHandler.removeCallbacks(mShowLoadingContainerRunnable);
|
||||||
|
handleLoadingContainer(true /* show */, animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showLoadingViewDelayed() {
|
||||||
|
mFgHandler.postDelayed(
|
||||||
|
mShowLoadingContainerRunnable, DELAY_SHOW_LOADING_CONTAINER_THRESHOLD_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleLoadingContainer(boolean done, boolean animate) {
|
||||||
|
handleLoadingContainer(mLoadingView, mContentView, done, animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show/hide loading view and content view.
|
||||||
|
*
|
||||||
|
* @param loading The loading spinner view
|
||||||
|
* @param content The content view
|
||||||
|
* @param done If true, content is set visible and loading is set invisible.
|
||||||
|
* @param animate Whether or not content/loading views should animate in/out.
|
||||||
|
*/
|
||||||
|
public static void handleLoadingContainer(View loading, View content, boolean done,
|
||||||
|
boolean animate) {
|
||||||
|
setViewShown(loading, !done, animate);
|
||||||
|
setViewShown(content, done, animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setViewShown(final View view, boolean shown, boolean animate) {
|
||||||
|
if (animate) {
|
||||||
|
Animation animation = AnimationUtils.loadAnimation(view.getContext(),
|
||||||
|
shown ? android.R.anim.fade_in : android.R.anim.fade_out);
|
||||||
|
if (shown) {
|
||||||
|
view.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
animation.setAnimationListener(new Animation.AnimationListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animation animation) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animation animation) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animation animation) {
|
||||||
|
view.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
view.startAnimation(animation);
|
||||||
|
} else {
|
||||||
|
view.clearAnimation();
|
||||||
|
view.setVisibility(shown ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -37,12 +37,10 @@ import com.android.settings.testutils.shadow.SettingsShadowResources;
|
|||||||
import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
|
import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
|
||||||
import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
|
import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
|
||||||
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
|
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
|
||||||
|
import com.android.settings.widget.LoadingViewController;
|
||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
import com.android.settingslib.applications.ApplicationsState.Callbacks;
|
|
||||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -53,10 +51,11 @@ import org.robolectric.annotation.Config;
|
|||||||
import org.robolectric.fakes.RoboMenuItem;
|
import org.robolectric.fakes.RoboMenuItem;
|
||||||
import org.robolectric.util.ReflectionHelpers;
|
import org.robolectric.util.ReflectionHelpers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.anyInt;
|
import static org.mockito.Matchers.anyInt;
|
||||||
import static org.mockito.Matchers.anyLong;
|
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
import static org.mockito.Mockito.doNothing;
|
import static org.mockito.Mockito.doNothing;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
@@ -170,12 +169,12 @@ public class ManageApplicationsTest {
|
|||||||
ReflectionHelpers.setField(fragment, "mLoadingContainer", mock(View.class));
|
ReflectionHelpers.setField(fragment, "mLoadingContainer", mock(View.class));
|
||||||
ReflectionHelpers.setField(fragment, "mListContainer", mock(View.class));
|
ReflectionHelpers.setField(fragment, "mListContainer", mock(View.class));
|
||||||
when(fragment.getActivity()).thenReturn(mock(Activity.class));
|
when(fragment.getActivity()).thenReturn(mock(Activity.class));
|
||||||
final Runnable showLoadingContainerRunnable = mock(Runnable.class);
|
|
||||||
final Handler handler = mock(Handler.class);
|
final Handler handler = mock(Handler.class);
|
||||||
final ManageApplications.ApplicationsAdapter adapter =
|
final ManageApplications.ApplicationsAdapter adapter =
|
||||||
spy(new ManageApplications.ApplicationsAdapter(mState, fragment, 0));
|
spy(new ManageApplications.ApplicationsAdapter(mState, fragment, 0));
|
||||||
ReflectionHelpers.setField(adapter, "mShowLoadingContainerRunnable",
|
final LoadingViewController loadingViewController =
|
||||||
showLoadingContainerRunnable);
|
mock(LoadingViewController.class);
|
||||||
|
ReflectionHelpers.setField(adapter, "mLoadingViewController", loadingViewController);
|
||||||
ReflectionHelpers.setField(adapter, "mFgHandler", handler);
|
ReflectionHelpers.setField(adapter, "mFgHandler", handler);
|
||||||
|
|
||||||
// app loading completed
|
// app loading completed
|
||||||
@@ -186,7 +185,7 @@ public class ManageApplicationsTest {
|
|||||||
|
|
||||||
adapter.updateLoading();
|
adapter.updateLoading();
|
||||||
|
|
||||||
verify(handler, never()).postDelayed(eq(showLoadingContainerRunnable), anyLong());
|
verify(loadingViewController, never()).showLoadingViewDelayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -195,12 +194,13 @@ public class ManageApplicationsTest {
|
|||||||
ReflectionHelpers.setField(fragment, "mLoadingContainer", mock(View.class));
|
ReflectionHelpers.setField(fragment, "mLoadingContainer", mock(View.class));
|
||||||
ReflectionHelpers.setField(fragment, "mListContainer", mock(View.class));
|
ReflectionHelpers.setField(fragment, "mListContainer", mock(View.class));
|
||||||
when(fragment.getActivity()).thenReturn(mock(Activity.class));
|
when(fragment.getActivity()).thenReturn(mock(Activity.class));
|
||||||
final Runnable showLoadingContainerRunnable = mock(Runnable.class);
|
|
||||||
final Handler handler = mock(Handler.class);
|
final Handler handler = mock(Handler.class);
|
||||||
final ManageApplications.ApplicationsAdapter adapter =
|
final ManageApplications.ApplicationsAdapter adapter =
|
||||||
spy(new ManageApplications.ApplicationsAdapter(mState, fragment, 0));
|
spy(new ManageApplications.ApplicationsAdapter(mState, fragment, 0));
|
||||||
ReflectionHelpers.setField(adapter, "mShowLoadingContainerRunnable",
|
final LoadingViewController loadingViewController =
|
||||||
showLoadingContainerRunnable);
|
mock(LoadingViewController.class);
|
||||||
|
ReflectionHelpers.setField(adapter, "mLoadingViewController", loadingViewController);
|
||||||
ReflectionHelpers.setField(adapter, "mFgHandler", handler);
|
ReflectionHelpers.setField(adapter, "mFgHandler", handler);
|
||||||
|
|
||||||
// app loading not yet completed
|
// app loading not yet completed
|
||||||
@@ -208,11 +208,11 @@ public class ManageApplicationsTest {
|
|||||||
|
|
||||||
adapter.updateLoading();
|
adapter.updateLoading();
|
||||||
|
|
||||||
verify(handler).postDelayed(eq(showLoadingContainerRunnable), anyLong());
|
verify(loadingViewController).showLoadingViewDelayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onRebuildComplete_shouldCancelDelayedRunnable() {
|
public void onRebuildComplete_shouldHideLoadingView() {
|
||||||
final Context context = RuntimeEnvironment.application;
|
final Context context = RuntimeEnvironment.application;
|
||||||
final ManageApplications fragment = mock(ManageApplications.class);
|
final ManageApplications fragment = mock(ManageApplications.class);
|
||||||
final View loadingContainer = mock(View.class);
|
final View loadingContainer = mock(View.class);
|
||||||
@@ -223,12 +223,12 @@ public class ManageApplicationsTest {
|
|||||||
ReflectionHelpers.setField(fragment, "mLoadingContainer", loadingContainer);
|
ReflectionHelpers.setField(fragment, "mLoadingContainer", loadingContainer);
|
||||||
ReflectionHelpers.setField(fragment, "mListContainer", listContainer);
|
ReflectionHelpers.setField(fragment, "mListContainer", listContainer);
|
||||||
when(fragment.getActivity()).thenReturn(mock(Activity.class));
|
when(fragment.getActivity()).thenReturn(mock(Activity.class));
|
||||||
final Runnable showLoadingContainerRunnable = mock(Runnable.class);
|
|
||||||
final Handler handler = mock(Handler.class);
|
final Handler handler = mock(Handler.class);
|
||||||
final ManageApplications.ApplicationsAdapter adapter =
|
final ManageApplications.ApplicationsAdapter adapter =
|
||||||
spy(new ManageApplications.ApplicationsAdapter(mState, fragment, 0));
|
spy(new ManageApplications.ApplicationsAdapter(mState, fragment, 0));
|
||||||
ReflectionHelpers.setField(adapter, "mShowLoadingContainerRunnable",
|
final LoadingViewController loadingViewController =
|
||||||
showLoadingContainerRunnable);
|
mock(LoadingViewController.class);
|
||||||
|
ReflectionHelpers.setField(adapter, "mLoadingViewController", loadingViewController);
|
||||||
ReflectionHelpers.setField(adapter, "mFgHandler", handler);
|
ReflectionHelpers.setField(adapter, "mFgHandler", handler);
|
||||||
ReflectionHelpers.setField(adapter, "mFilterMode", -1);
|
ReflectionHelpers.setField(adapter, "mFilterMode", -1);
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ public class ManageApplicationsTest {
|
|||||||
|
|
||||||
adapter.onRebuildComplete(null);
|
adapter.onRebuildComplete(null);
|
||||||
|
|
||||||
verify(handler).removeCallbacks(showLoadingContainerRunnable);
|
verify(loadingViewController).showContent(true /* animate */);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpOptionMenus() {
|
private void setUpOptionMenus() {
|
||||||
|
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.widget;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.util.ReflectionHelpers;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyLong;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class LoadingViewControllerTest {
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private View mLoadingView;
|
||||||
|
private View mContentView;
|
||||||
|
|
||||||
|
private LoadingViewController mController;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mContext = RuntimeEnvironment.application;
|
||||||
|
mLoadingView = new View(mContext);
|
||||||
|
mContentView = new View(mContext);
|
||||||
|
|
||||||
|
mController = new LoadingViewController(mLoadingView, mContentView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void showContent_shouldSetContentVisible() {
|
||||||
|
mController.showContent(false /* animate */);
|
||||||
|
|
||||||
|
assertThat(mContentView.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void showLoadingViewDelayed_shouldPostRunnable() {
|
||||||
|
final Handler handler = mock(Handler.class);
|
||||||
|
ReflectionHelpers.setField(mController, "mFgHandler", handler);
|
||||||
|
mController.showLoadingViewDelayed();
|
||||||
|
|
||||||
|
verify(handler).postDelayed(any(Runnable.class), anyLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user