Convert SettingsLib Lifecycle to Flatfoot

Bug: 69257739
Test: m -j RunSettingsLibRoboTests
Change-Id: Iaf14f6f26689a54248bd27cffce0423e857181b9
This commit is contained in:
Tony Mantler
2017-11-10 13:16:59 -08:00
parent d3fe8f09c8
commit ece840b115
17 changed files with 248 additions and 75 deletions

View File

@@ -13,6 +13,10 @@ LOCAL_SHARED_ANDROID_LIBRARIES := \
android-support-v7-appcompat \
android-support-v14-preference
LOCAL_SHARED_JAVA_LIBRARIES := \
apptoolkit-lifecycle-common \
apptoolkit-lifecycle-runtime
LOCAL_STATIC_JAVA_LIBRARY := legacy-android-test
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res

View File

@@ -15,11 +15,18 @@
*/
package com.android.settingslib.core.lifecycle;
import static android.arch.lifecycle.Lifecycle.Event.ON_ANY;
import android.annotation.UiThread;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.LifecycleRegistry;
import android.arch.lifecycle.OnLifecycleEvent;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -44,18 +51,46 @@ import java.util.List;
/**
* Dispatcher for lifecycle events.
*/
public class Lifecycle {
public class Lifecycle extends LifecycleRegistry {
private static final String TAG = "LifecycleObserver";
protected final List<LifecycleObserver> mObservers = new ArrayList<>();
private final List<LifecycleObserver> mObservers = new ArrayList<>();
private final LifecycleProxy mProxy = new LifecycleProxy();
/**
* Creates a new LifecycleRegistry for the given provider.
* <p>
* You should usually create this inside your LifecycleOwner class's constructor and hold
* onto the same instance.
*
* @param provider The owner LifecycleOwner
*/
public Lifecycle(@NonNull LifecycleOwner provider) {
super(provider);
addObserver(mProxy);
}
/**
* Registers a new observer of lifecycle events.
*/
@UiThread
public <T extends LifecycleObserver> T addObserver(T observer) {
@Override
public void addObserver(android.arch.lifecycle.LifecycleObserver observer) {
ThreadUtils.ensureMainThread();
mObservers.add(observer);
return observer;
super.addObserver(observer);
if (observer instanceof LifecycleObserver) {
mObservers.add((LifecycleObserver) observer);
}
}
@UiThread
@Override
public void removeObserver(android.arch.lifecycle.LifecycleObserver observer) {
ThreadUtils.ensureMainThread();
super.removeObserver(observer);
if (observer instanceof LifecycleObserver) {
mObservers.remove(observer);
}
}
public void onAttach(Context context) {
@@ -67,6 +102,8 @@ public class Lifecycle {
}
}
// This method is not called from the proxy because it does not have access to the
// savedInstanceState
public void onCreate(Bundle savedInstanceState) {
for (int i = 0, size = mObservers.size(); i < size; i++) {
final LifecycleObserver observer = mObservers.get(i);
@@ -76,7 +113,7 @@ public class Lifecycle {
}
}
public void onStart() {
private void onStart() {
for (int i = 0, size = mObservers.size(); i < size; i++) {
final LifecycleObserver observer = mObservers.get(i);
if (observer instanceof OnStart) {
@@ -94,7 +131,7 @@ public class Lifecycle {
}
}
public void onResume() {
private void onResume() {
for (int i = 0, size = mObservers.size(); i < size; i++) {
final LifecycleObserver observer = mObservers.get(i);
if (observer instanceof OnResume) {
@@ -103,7 +140,7 @@ public class Lifecycle {
}
}
public void onPause() {
private void onPause() {
for (int i = 0, size = mObservers.size(); i < size; i++) {
final LifecycleObserver observer = mObservers.get(i);
if (observer instanceof OnPause) {
@@ -121,7 +158,7 @@ public class Lifecycle {
}
}
public void onStop() {
private void onStop() {
for (int i = 0, size = mObservers.size(); i < size; i++) {
final LifecycleObserver observer = mObservers.get(i);
if (observer instanceof OnStop) {
@@ -130,7 +167,7 @@ public class Lifecycle {
}
}
public void onDestroy() {
private void onDestroy() {
for (int i = 0, size = mObservers.size(); i < size; i++) {
final LifecycleObserver observer = mObservers.get(i);
if (observer instanceof OnDestroy) {
@@ -168,4 +205,34 @@ public class Lifecycle {
}
return false;
}
private class LifecycleProxy
implements android.arch.lifecycle.LifecycleObserver {
@OnLifecycleEvent(ON_ANY)
public void onLifecycleEvent(LifecycleOwner owner, Event event) {
switch (event) {
case ON_CREATE:
// onCreate is called directly since we don't have savedInstanceState here
break;
case ON_START:
onStart();
break;
case ON_RESUME:
onResume();
break;
case ON_PAUSE:
onPause();
break;
case ON_STOP:
onStop();
break;
case ON_DESTROY:
onDestroy();
break;
case ON_ANY:
Log.wtf(TAG, "Should not receive an 'ANY' event!");
break;
}
}
}
}

View File

@@ -17,6 +17,9 @@ package com.android.settingslib.core.lifecycle;
/**
* Observer of lifecycle events.
* @deprecated use {@link android.arch.lifecycle.LifecycleObserver} instead
*/
public interface LifecycleObserver {
@Deprecated
public interface LifecycleObserver extends
android.arch.lifecycle.LifecycleObserver {
}

View File

@@ -15,8 +15,16 @@
*/
package com.android.settingslib.core.lifecycle;
import static android.arch.lifecycle.Lifecycle.Event.ON_CREATE;
import static android.arch.lifecycle.Lifecycle.Event.ON_DESTROY;
import static android.arch.lifecycle.Lifecycle.Event.ON_PAUSE;
import static android.arch.lifecycle.Lifecycle.Event.ON_RESUME;
import static android.arch.lifecycle.Lifecycle.Event.ON_START;
import static android.arch.lifecycle.Lifecycle.Event.ON_STOP;
import android.annotation.Nullable;
import android.app.Activity;
import android.arch.lifecycle.LifecycleOwner;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.view.Menu;
@@ -25,17 +33,19 @@ import android.view.MenuItem;
/**
* {@link Activity} that has hooks to observe activity lifecycle events.
*/
public class ObservableActivity extends Activity {
public class ObservableActivity extends Activity implements LifecycleOwner {
private final Lifecycle mLifecycle = new Lifecycle();
private final Lifecycle mLifecycle = new Lifecycle(this);
protected Lifecycle getLifecycle() {
public Lifecycle getLifecycle() {
return mLifecycle;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mLifecycle.onAttach(this);
mLifecycle.onCreate(savedInstanceState);
mLifecycle.handleLifecycleEvent(ON_CREATE);
super.onCreate(savedInstanceState);
}
@@ -43,36 +53,38 @@ public class ObservableActivity extends Activity {
public void onCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
mLifecycle.onAttach(this);
mLifecycle.onCreate(savedInstanceState);
mLifecycle.handleLifecycleEvent(ON_CREATE);
super.onCreate(savedInstanceState, persistentState);
}
@Override
protected void onStart() {
mLifecycle.onStart();
mLifecycle.handleLifecycleEvent(ON_START);
super.onStart();
}
@Override
protected void onResume() {
mLifecycle.onResume();
mLifecycle.handleLifecycleEvent(ON_RESUME);
super.onResume();
}
@Override
protected void onPause() {
mLifecycle.onPause();
mLifecycle.handleLifecycleEvent(ON_PAUSE);
super.onPause();
}
@Override
protected void onStop() {
mLifecycle.onStop();
mLifecycle.handleLifecycleEvent(ON_STOP);
super.onStop();
}
@Override
protected void onDestroy() {
mLifecycle.onDestroy();
mLifecycle.handleLifecycleEvent(ON_DESTROY);
super.onDestroy();
}

View File

@@ -15,9 +15,17 @@
*/
package com.android.settingslib.core.lifecycle;
import static android.arch.lifecycle.Lifecycle.Event.ON_CREATE;
import static android.arch.lifecycle.Lifecycle.Event.ON_DESTROY;
import static android.arch.lifecycle.Lifecycle.Event.ON_PAUSE;
import static android.arch.lifecycle.Lifecycle.Event.ON_RESUME;
import static android.arch.lifecycle.Lifecycle.Event.ON_START;
import static android.arch.lifecycle.Lifecycle.Event.ON_STOP;
import android.app.DialogFragment;
import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
import android.support.annotation.VisibleForTesting;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -25,9 +33,9 @@ import android.view.MenuItem;
/**
* {@link DialogFragment} that has hooks to observe fragment lifecycle events.
*/
public class ObservableDialogFragment extends DialogFragment {
public class ObservableDialogFragment extends DialogFragment implements LifecycleOwner {
protected final Lifecycle mLifecycle = createLifecycle();
protected final Lifecycle mLifecycle = new Lifecycle(this);
@Override
public void onAttach(Context context) {
@@ -35,33 +43,40 @@ public class ObservableDialogFragment extends DialogFragment {
mLifecycle.onAttach(context);
}
@Override
public void onCreate(Bundle savedInstanceState) {
mLifecycle.onCreate(savedInstanceState);
mLifecycle.handleLifecycleEvent(ON_CREATE);
super.onCreate(savedInstanceState);
}
@Override
public void onStart() {
mLifecycle.onStart();
mLifecycle.handleLifecycleEvent(ON_START);
super.onStart();
}
@Override
public void onResume() {
mLifecycle.onResume();
mLifecycle.handleLifecycleEvent(ON_RESUME);
super.onResume();
}
@Override
public void onPause() {
mLifecycle.onPause();
mLifecycle.handleLifecycleEvent(ON_PAUSE);
super.onPause();
}
@Override
public void onStop() {
mLifecycle.onStop();
mLifecycle.handleLifecycleEvent(ON_STOP);
super.onStop();
}
@Override
public void onDestroy() {
mLifecycle.onDestroy();
mLifecycle.handleLifecycleEvent(ON_DESTROY);
super.onDestroy();
}
@@ -86,9 +101,8 @@ public class ObservableDialogFragment extends DialogFragment {
return lifecycleHandled;
}
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
/** @return a new lifecycle. */
public static Lifecycle createLifecycle() {
return new Lifecycle();
@Override
public Lifecycle getLifecycle() {
return mLifecycle;
}
}

View File

@@ -16,19 +16,27 @@
package com.android.settingslib.core.lifecycle;
import static android.arch.lifecycle.Lifecycle.Event.ON_CREATE;
import static android.arch.lifecycle.Lifecycle.Event.ON_DESTROY;
import static android.arch.lifecycle.Lifecycle.Event.ON_PAUSE;
import static android.arch.lifecycle.Lifecycle.Event.ON_RESUME;
import static android.arch.lifecycle.Lifecycle.Event.ON_START;
import static android.arch.lifecycle.Lifecycle.Event.ON_STOP;
import android.annotation.CallSuper;
import android.app.Fragment;
import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
public class ObservableFragment extends Fragment {
public class ObservableFragment extends Fragment implements LifecycleOwner {
private final Lifecycle mLifecycle = new Lifecycle();
private final Lifecycle mLifecycle = new Lifecycle(this);
protected Lifecycle getLifecycle() {
public Lifecycle getLifecycle() {
return mLifecycle;
}
@@ -43,6 +51,7 @@ public class ObservableFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
mLifecycle.onCreate(savedInstanceState);
mLifecycle.handleLifecycleEvent(ON_CREATE);
super.onCreate(savedInstanceState);
}
@@ -56,35 +65,35 @@ public class ObservableFragment extends Fragment {
@CallSuper
@Override
public void onStart() {
mLifecycle.onStart();
mLifecycle.handleLifecycleEvent(ON_START);
super.onStart();
}
@CallSuper
@Override
public void onStop() {
mLifecycle.onStop();
super.onStop();
}
@CallSuper
@Override
public void onResume() {
mLifecycle.onResume();
mLifecycle.handleLifecycleEvent(ON_RESUME);
super.onResume();
}
@CallSuper
@Override
public void onPause() {
mLifecycle.onPause();
mLifecycle.handleLifecycleEvent(ON_PAUSE);
super.onPause();
}
@CallSuper
@Override
public void onStop() {
mLifecycle.handleLifecycleEvent(ON_STOP);
super.onStop();
}
@CallSuper
@Override
public void onDestroy() {
mLifecycle.onDestroy();
mLifecycle.handleLifecycleEvent(ON_DESTROY);
super.onDestroy();
}

View File

@@ -16,7 +16,15 @@
package com.android.settingslib.core.lifecycle;
import static android.arch.lifecycle.Lifecycle.Event.ON_CREATE;
import static android.arch.lifecycle.Lifecycle.Event.ON_DESTROY;
import static android.arch.lifecycle.Lifecycle.Event.ON_PAUSE;
import static android.arch.lifecycle.Lifecycle.Event.ON_RESUME;
import static android.arch.lifecycle.Lifecycle.Event.ON_START;
import static android.arch.lifecycle.Lifecycle.Event.ON_STOP;
import android.annotation.CallSuper;
import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
import android.os.Bundle;
import android.support.v14.preference.PreferenceFragment;
@@ -28,11 +36,12 @@ import android.view.MenuItem;
/**
* {@link PreferenceFragment} that has hooks to observe fragment lifecycle events.
*/
public abstract class ObservablePreferenceFragment extends PreferenceFragment {
public abstract class ObservablePreferenceFragment extends PreferenceFragment
implements LifecycleOwner {
private final Lifecycle mLifecycle = new Lifecycle();
private final Lifecycle mLifecycle = new Lifecycle(this);
protected Lifecycle getLifecycle() {
public Lifecycle getLifecycle() {
return mLifecycle;
}
@@ -47,6 +56,7 @@ public abstract class ObservablePreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
mLifecycle.onCreate(savedInstanceState);
mLifecycle.handleLifecycleEvent(ON_CREATE);
super.onCreate(savedInstanceState);
}
@@ -66,35 +76,35 @@ public abstract class ObservablePreferenceFragment extends PreferenceFragment {
@CallSuper
@Override
public void onStart() {
mLifecycle.onStart();
mLifecycle.handleLifecycleEvent(ON_START);
super.onStart();
}
@CallSuper
@Override
public void onStop() {
mLifecycle.onStop();
super.onStop();
}
@CallSuper
@Override
public void onResume() {
mLifecycle.onResume();
mLifecycle.handleLifecycleEvent(ON_RESUME);
super.onResume();
}
@CallSuper
@Override
public void onPause() {
mLifecycle.onPause();
mLifecycle.handleLifecycleEvent(ON_PAUSE);
super.onPause();
}
@CallSuper
@Override
public void onStop() {
mLifecycle.handleLifecycleEvent(ON_STOP);
super.onStop();
}
@CallSuper
@Override
public void onDestroy() {
mLifecycle.onDestroy();
mLifecycle.handleLifecycleEvent(ON_DESTROY);
super.onDestroy();
}

View File

@@ -17,6 +17,10 @@ package com.android.settingslib.core.lifecycle.events;
import android.content.Context;
/**
* @deprecated pass {@link Context} in constructor instead
*/
@Deprecated
public interface OnAttach {
void onAttach(Context context);
}

View File

@@ -16,8 +16,14 @@
package com.android.settingslib.core.lifecycle.events;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.OnLifecycleEvent;
import android.os.Bundle;
/**
* @deprecated use {@link OnLifecycleEvent(Lifecycle.Event) }
*/
@Deprecated
public interface OnCreate {
void onCreate(Bundle savedInstanceState);
}

View File

@@ -15,6 +15,13 @@
*/
package com.android.settingslib.core.lifecycle.events;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.OnLifecycleEvent;
/**
* @deprecated use {@link OnLifecycleEvent(Lifecycle.Event) }
*/
@Deprecated
public interface OnDestroy {
void onDestroy();
}

View File

@@ -15,6 +15,13 @@
*/
package com.android.settingslib.core.lifecycle.events;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.OnLifecycleEvent;
/**
* @deprecated use {@link OnLifecycleEvent(Lifecycle.Event) }
*/
@Deprecated
public interface OnPause {
void onPause();
}

View File

@@ -15,6 +15,13 @@
*/
package com.android.settingslib.core.lifecycle.events;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.OnLifecycleEvent;
/**
* @deprecated use {@link OnLifecycleEvent(Lifecycle.Event)}
*/
@Deprecated
public interface OnResume {
void onResume();
}

View File

@@ -15,7 +15,13 @@
*/
package com.android.settingslib.core.lifecycle.events;
public interface OnStart {
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.OnLifecycleEvent;
/**
* @deprecated use {@link OnLifecycleEvent(Lifecycle.Event) }
*/
@Deprecated
public interface OnStart {
void onStart();
}

View File

@@ -15,7 +15,13 @@
*/
package com.android.settingslib.core.lifecycle.events;
public interface OnStop {
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.OnLifecycleEvent;
/**
* @deprecated use {@link OnLifecycleEvent(Lifecycle.Event) }
*/
@Deprecated
public interface OnStop {
void onStop();
}

View File

@@ -15,6 +15,10 @@
*/
package com.android.settingslib.core.lifecycle;
import static android.arch.lifecycle.Lifecycle.Event.ON_START;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.view.Menu;
import android.view.MenuInflater;
@@ -32,6 +36,7 @@ import com.android.settingslib.core.lifecycle.events.OnResume;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
@@ -39,12 +44,12 @@ import org.robolectric.android.controller.ActivityController;
import org.robolectric.android.controller.FragmentController;
import org.robolectric.annotation.Config;
import static com.google.common.truth.Truth.assertThat;
@RunWith(SettingsLibRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class LifecycleTest {
private Lifecycle mLifecycle;
public static class TestDialogFragment extends ObservableDialogFragment {
final TestObserver mFragObserver;
@@ -139,6 +144,11 @@ public class LifecycleTest {
}
}
@Before
public void setUp() {
mLifecycle = new Lifecycle(() -> mLifecycle);
}
@Test
public void runThroughActivityLifecycles_shouldObserveEverything() {
ActivityController<TestActivity> ac = Robolectric.buildActivity(TestActivity.class);
@@ -212,9 +222,8 @@ public class LifecycleTest {
@Test
public void addObserverDuringObserve_shoudNotCrash() {
Lifecycle lifecycle = new Lifecycle();
lifecycle.addObserver(new OnStartObserver(lifecycle));
lifecycle.onStart();
mLifecycle.addObserver(new OnStartObserver(mLifecycle));
mLifecycle.handleLifecycleEvent(ON_START);
}
private static class OptionItemAccepter implements LifecycleObserver, OnOptionsItemSelected {

View File

@@ -44,7 +44,7 @@ import org.robolectric.annotation.Config;
shadows = SystemPropertiesTestImpl.class)
public class LogpersistPreferenceControllerTest {
private Lifecycle mLifecycle = new Lifecycle();
private Lifecycle mLifecycle;
@Mock
private ListPreference mListPreference;
@@ -57,6 +57,7 @@ public class LogpersistPreferenceControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
SystemProperties.set("ro.debuggable", "1");
mLifecycle = new Lifecycle(() -> mLifecycle);
mController = new AbstractLogpersistPreferenceController(RuntimeEnvironment.application,
mLifecycle) {
@Override

View File

@@ -16,6 +16,14 @@
package com.android.settingslib.widget;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceScreen;
@@ -32,13 +40,6 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(SettingsLibRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class FooterPreferenceMixinTest {
@@ -54,7 +55,7 @@ public class FooterPreferenceMixinTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycle = new Lifecycle();
mLifecycle = new Lifecycle(() -> mLifecycle);
when(mFragment.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
when(mFragment.getPreferenceManager().getContext())
.thenReturn(ShadowApplication.getInstance().getApplicationContext());