Java8 interface for LifecycleObserver
Test: LifecycleObserversTest
bug: 65296790
Change-Id: I127a172f3c9e2aeaecff9415a9f8b4a3b233aba7
diff --git a/app-toolkit/settings.gradle b/app-toolkit/settings.gradle
index 31fc0e1..aa0db94 100644
--- a/app-toolkit/settings.gradle
+++ b/app-toolkit/settings.gradle
@@ -57,6 +57,9 @@
include ':lifecycle:common'
project(':lifecycle:common').projectDir = new File(supportRoot, "lifecycle/common")
+include ':lifecycle:common-java8'
+project(':lifecycle:common-java8').projectDir = new File(supportRoot, "lifecycle/common-java8")
+
include ':lifecycle:compiler'
project(':lifecycle:compiler').projectDir = new File(supportRoot, "lifecycle/compiler")
diff --git a/buildSrc/src/main/groovy/android/support/SupportJavaLibraryPlugin.groovy b/buildSrc/src/main/groovy/android/support/SupportJavaLibraryPlugin.groovy
index 443df5a..ae0d55c 100644
--- a/buildSrc/src/main/groovy/android/support/SupportJavaLibraryPlugin.groovy
+++ b/buildSrc/src/main/groovy/android/support/SupportJavaLibraryPlugin.groovy
@@ -33,10 +33,13 @@
SupportLibraryMavenUploader.apply(project, supportLibraryExtension);
project.apply(ImmutableMap.of("plugin", "java"));
-
- project.compileJava {
- sourceCompatibility = JavaVersion.VERSION_1_7
- targetCompatibility = JavaVersion.VERSION_1_7
+ project.afterEvaluate {
+ project.compileJava {
+ def version = supportLibraryExtension.java8Library ?
+ JavaVersion.VERSION_1_8 : JavaVersion.VERSION_1_7
+ sourceCompatibility = version
+ targetCompatibility = version
+ }
}
}
}
\ No newline at end of file
diff --git a/buildSrc/src/main/groovy/android/support/SupportLibraryExtension.groovy b/buildSrc/src/main/groovy/android/support/SupportLibraryExtension.groovy
index 2aacf60..93afb9a 100644
--- a/buildSrc/src/main/groovy/android/support/SupportLibraryExtension.groovy
+++ b/buildSrc/src/main/groovy/android/support/SupportLibraryExtension.groovy
@@ -33,6 +33,7 @@
String inceptionYear;
String url = SUPPORT_URL;
Collection<License> licenses = [];
+ boolean java8Library = false;
boolean publish = false;
SupportLibraryExtension(Project project) {
diff --git a/lifecycle/common-java8/build.gradle b/lifecycle/common-java8/build.gradle
new file mode 100644
index 0000000..fccc813
--- /dev/null
+++ b/lifecycle/common-java8/build.gradle
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+import android.support.LibraryVersions;
+import android.support.SupportLibraryExtension;
+
+apply plugin: android.support.SupportJavaLibraryPlugin
+
+dependencies {
+ testCompile libs.junit
+ testCompile libs.mockito_core
+ compile project(":lifecycle:common")
+ compile libs.support.annotations
+}
+
+createAndroidCheckstyle(project)
+
+version = LibraryVersions.LIFECYCLES_EXT.toString()
+supportLibrary {
+ name 'Android Lifecycle-Common for Java 8 Language'
+ publish true
+ inceptionYear '2017'
+ description "Android Lifecycle-Common for Java 8 Language"
+ url SupportLibraryExtension.ARCHITECTURE_URL
+ java8Library true
+}
diff --git a/lifecycle/common-java8/src/main/java/android/arch/lifecycle/DefaultLifecycleObserver.java b/lifecycle/common-java8/src/main/java/android/arch/lifecycle/DefaultLifecycleObserver.java
new file mode 100644
index 0000000..77a7dfd
--- /dev/null
+++ b/lifecycle/common-java8/src/main/java/android/arch/lifecycle/DefaultLifecycleObserver.java
@@ -0,0 +1,98 @@
+/*
+ * 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 android.arch.lifecycle;
+
+/**
+ * Callback interface for listening to {@link LifecycleOwner} state changes.
+ * <p>
+ * If you use Java 8 language, <b>always</b> prefer it over annotations.
+ */
+@SuppressWarnings("unused")
+public interface DefaultLifecycleObserver extends FullLifecycleObserver {
+
+ /**
+ * Notifies that {@code ON_CREATE} event occurred.
+ * <p>
+ * This method will be called after the {@link LifecycleOwner}'s {@code onCreate}
+ * method returns.
+ *
+ * @param owner the component, whose state was changed
+ */
+ @Override
+ default void onCreate(LifecycleOwner owner) {
+ }
+
+ /**
+ * Notifies that {@code ON_START} event occurred.
+ * <p>
+ * This method will be called after the {@link LifecycleOwner}'s {@code onStart} method returns.
+ *
+ * @param owner the component, whose state was changed
+ */
+ @Override
+ default void onStart(LifecycleOwner owner) {
+ }
+
+ /**
+ * Notifies that {@code ON_RESUME} event occurred.
+ * <p>
+ * This method will be called after the {@link LifecycleOwner}'s {@code onResume}
+ * method returns.
+ *
+ * @param owner the component, whose state was changed
+ */
+ @Override
+ default void onResume(LifecycleOwner owner) {
+ }
+
+ /**
+ * Notifies that {@code ON_PAUSE} event occurred.
+ * <p>
+ * This method will be called before the {@link LifecycleOwner}'s {@code onPause} method
+ * is called.
+ *
+ * @param owner the component, whose state was changed
+ */
+ @Override
+ default void onPause(LifecycleOwner owner) {
+ }
+
+ /**
+ * Notifies that {@code ON_STOP} event occurred.
+ * <p>
+ * This method will be called before the {@link LifecycleOwner}'s {@code onStop} method
+ * is called.
+ *
+ * @param owner the component, whose state was changed
+ */
+ @Override
+ default void onStop(LifecycleOwner owner) {
+ }
+
+ /**
+ * Notifies that {@code ON_DESTROY} event occurred.
+ * <p>
+ * This method will be called before the {@link LifecycleOwner}'s {@code onStop} method
+ * is called.
+ *
+ * @param owner the component, whose state was changed
+ */
+ @Override
+ default void onDestroy(LifecycleOwner owner) {
+ }
+}
+
diff --git a/lifecycle/common/src/main/java/android/arch/lifecycle/FullLifecycleObserver.java b/lifecycle/common/src/main/java/android/arch/lifecycle/FullLifecycleObserver.java
new file mode 100644
index 0000000..f179274
--- /dev/null
+++ b/lifecycle/common/src/main/java/android/arch/lifecycle/FullLifecycleObserver.java
@@ -0,0 +1,32 @@
+/*
+ * 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 android.arch.lifecycle;
+
+interface FullLifecycleObserver extends LifecycleObserver {
+
+ void onCreate(LifecycleOwner owner);
+
+ void onStart(LifecycleOwner owner);
+
+ void onResume(LifecycleOwner owner);
+
+ void onPause(LifecycleOwner owner);
+
+ void onStop(LifecycleOwner owner);
+
+ void onDestroy(LifecycleOwner owner);
+}
diff --git a/lifecycle/common/src/main/java/android/arch/lifecycle/FullLifecycleObserverAdapter.java b/lifecycle/common/src/main/java/android/arch/lifecycle/FullLifecycleObserverAdapter.java
new file mode 100644
index 0000000..0a91a66
--- /dev/null
+++ b/lifecycle/common/src/main/java/android/arch/lifecycle/FullLifecycleObserverAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * 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 android.arch.lifecycle;
+
+class FullLifecycleObserverAdapter implements GenericLifecycleObserver {
+
+ private final FullLifecycleObserver mObserver;
+
+ FullLifecycleObserverAdapter(FullLifecycleObserver observer) {
+ mObserver = observer;
+ }
+
+ @Override
+ public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
+ switch (event) {
+ case ON_CREATE:
+ mObserver.onCreate(source);
+ break;
+ case ON_START:
+ mObserver.onStart(source);
+ break;
+ case ON_RESUME:
+ mObserver.onResume(source);
+ break;
+ case ON_PAUSE:
+ mObserver.onPause(source);
+ break;
+ case ON_STOP:
+ mObserver.onStop(source);
+ break;
+ case ON_DESTROY:
+ mObserver.onDestroy(source);
+ break;
+ case ON_ANY:
+ throw new IllegalArgumentException("ON_ANY must not been send by anybody");
+ }
+ }
+}
diff --git a/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycle.java b/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycle.java
index fcbd50a..02db5ff 100644
--- a/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycle.java
+++ b/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycle.java
@@ -34,7 +34,21 @@
* before {@link android.app.Activity#onStop onStop} is called.
* This gives you certain guarantees on which state the owner is in.
* <p>
- * Lifecycle events are observed using annotations.
+ * If you use <b>Java 8 Language</b>, then observe events with {@link DefaultLifecycleObserver}.
+ * To include it you should add {@code "android.arch.lifecycle:common-java8:<version>"} to your
+ * build.gradle file.
+ * <pre>
+ * class TestObserver implements DefaultLifecycleObserver {
+ * {@literal @}Override
+ * public void onCreate(LifecycleOwner owner) {
+ * // your code
+ * }
+ * }
+ * </pre>
+ * If you use <b>Java 7 Language</b>, Lifecycle events are observed using annotations.
+ * Once Java 8 Language becomes mainstream on Android, annotations will be deprecated, so between
+ * {@link DefaultLifecycleObserver} and annotations,
+ * you must always prefer {@code DefaultLifecycleObserver}.
* <pre>
* class TestObserver implements LifecycleObserver {
* {@literal @}OnLifecycleEvent(ON_STOP)
@@ -42,16 +56,6 @@
* }
* </pre>
* <p>
- * Multiple methods can observe the same event.
- * <pre>
- * class TestObserver implements LifecycleObserver {
- * {@literal @}OnLifecycleEvent(ON_STOP)
- * void onStoppedFirst() {}
- * {@literal @}OnLifecycleEvent(ON_STOP)
- * void onStoppedSecond() {}
- * }
- * </pre>
- * <p>
* Observer methods can receive zero or one argument.
* If used, the first argument must be of type {@link LifecycleOwner}.
* Methods annotated with {@link Event#ON_ANY} can receive the second argument, which must be
diff --git a/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycling.java b/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycling.java
index 3a5c0b9..0dfa2e1 100644
--- a/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycling.java
+++ b/lifecycle/common/src/main/java/android/arch/lifecycle/Lifecycling.java
@@ -47,6 +47,10 @@
@NonNull
static GenericLifecycleObserver getCallback(Object object) {
+ if (object instanceof FullLifecycleObserver) {
+ return new FullLifecycleObserverAdapter((FullLifecycleObserver) object);
+ }
+
if (object instanceof GenericLifecycleObserver) {
return (GenericLifecycleObserver) object;
}
diff --git a/lifecycle/common/src/test/java/android/arch/lifecycle/FullLifecycleObserverTest.java b/lifecycle/common/src/test/java/android/arch/lifecycle/FullLifecycleObserverTest.java
new file mode 100644
index 0000000..def6755
--- /dev/null
+++ b/lifecycle/common/src/test/java/android/arch/lifecycle/FullLifecycleObserverTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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 android.arch.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 static android.arch.lifecycle.Lifecycle.State.CREATED;
+import static android.arch.lifecycle.Lifecycle.State.INITIALIZED;
+import static android.arch.lifecycle.Lifecycle.State.RESUMED;
+import static android.arch.lifecycle.Lifecycle.State.STARTED;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+
+@RunWith(JUnit4.class)
+public class FullLifecycleObserverTest {
+ private LifecycleOwner mOwner;
+ private Lifecycle mLifecycle;
+
+ @Before
+ public void initMocks() {
+ mOwner = mock(LifecycleOwner.class);
+ mLifecycle = mock(Lifecycle.class);
+ when(mOwner.getLifecycle()).thenReturn(mLifecycle);
+ }
+
+ @Test
+ public void eachEvent() {
+ FullLifecycleObserver obj = mock(FullLifecycleObserver.class);
+ FullLifecycleObserverAdapter observer = new FullLifecycleObserverAdapter(obj);
+ when(mLifecycle.getCurrentState()).thenReturn(CREATED);
+
+ observer.onStateChanged(mOwner, ON_CREATE);
+ InOrder inOrder = Mockito.inOrder(obj);
+ inOrder.verify(obj).onCreate(mOwner);
+ reset(obj);
+
+ when(mLifecycle.getCurrentState()).thenReturn(STARTED);
+ observer.onStateChanged(mOwner, ON_START);
+ inOrder.verify(obj).onStart(mOwner);
+ reset(obj);
+
+ when(mLifecycle.getCurrentState()).thenReturn(RESUMED);
+ observer.onStateChanged(mOwner, ON_RESUME);
+ inOrder.verify(obj).onResume(mOwner);
+ reset(obj);
+
+ when(mLifecycle.getCurrentState()).thenReturn(STARTED);
+ observer.onStateChanged(mOwner, ON_PAUSE);
+ inOrder.verify(obj).onPause(mOwner);
+ reset(obj);
+
+ when(mLifecycle.getCurrentState()).thenReturn(CREATED);
+ observer.onStateChanged(mOwner, ON_STOP);
+ inOrder.verify(obj).onStop(mOwner);
+ reset(obj);
+
+ when(mLifecycle.getCurrentState()).thenReturn(INITIALIZED);
+ observer.onStateChanged(mOwner, ON_DESTROY);
+ inOrder.verify(obj).onDestroy(mOwner);
+ reset(obj);
+ }
+}