From 4a9372200464216238844aa8dffe274f73b35b23 Mon Sep 17 00:00:00 2001 From: Guillaume Lung Date: Wed, 9 Mar 2016 19:16:33 +0100 Subject: [PATCH] Fix: When type Parent->Child, enable Dispatcher to bind LightCycle. The processor internaly lift the LightCycle to LightCycle. --- .../AppForegroundStateProvider.java | 34 +++ .../sample/real_world/SampleActivity.java | 1 + .../lightcycle/LightCycleBinder.java | 201 ++++++++++++++++++ .../lightcycle/LightCycleDispatcher.java | 1 + .../lightcycle/LightCycleProcessor.java | 72 +++++-- .../lightcycle/LightCycleProcessorTest.java | 41 +++- .../resources/com/test/ValidTestActivity.java | 4 +- .../resources/com/test/ValidTestFragment.java | 4 +- .../com/test/ValidTestHierarchyActivity.java | 30 +++ .../com/test/ValidTestSupportFragment.java | 8 +- .../lightcycle/sample/MyBaseActivity.java | 96 +++++++++ .../lightcycle/sample/SampleActivity.java | 25 +++ 12 files changed, 491 insertions(+), 26 deletions(-) create mode 100644 examples/real-world/src/main/java/com/soundcloud/lightcycle/sample/real_world/AppForegroundStateProvider.java create mode 100644 lightcycle-processor/src/test/resources/com/test/ValidTestHierarchyActivity.java create mode 100644 lightcycle-sample/src/main/java/com/soundcloud/lightcycle/sample/MyBaseActivity.java create mode 100644 lightcycle-sample/src/main/java/com/soundcloud/lightcycle/sample/SampleActivity.java diff --git a/examples/real-world/src/main/java/com/soundcloud/lightcycle/sample/real_world/AppForegroundStateProvider.java b/examples/real-world/src/main/java/com/soundcloud/lightcycle/sample/real_world/AppForegroundStateProvider.java new file mode 100644 index 0000000..ec90258 --- /dev/null +++ b/examples/real-world/src/main/java/com/soundcloud/lightcycle/sample/real_world/AppForegroundStateProvider.java @@ -0,0 +1,34 @@ +package com.soundcloud.lightcycle.sample.real_world; + +import com.soundcloud.lightcycle.DefaultActivityLightCycle; + +import android.app.Activity; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +class AppForegroundStateProvider extends DefaultActivityLightCycle { + + private boolean isForeground; + + @Inject + public AppForegroundStateProvider() { + isForeground = false; + } + + @Override + public void onResume(Activity activity) { + isForeground = true; + } + + @Override + public void onPause(Activity activity) { + isForeground = false; + } + + public boolean isForeground() { + return isForeground; + } + +} diff --git a/examples/real-world/src/main/java/com/soundcloud/lightcycle/sample/real_world/SampleActivity.java b/examples/real-world/src/main/java/com/soundcloud/lightcycle/sample/real_world/SampleActivity.java index a70dce0..2fe0225 100644 --- a/examples/real-world/src/main/java/com/soundcloud/lightcycle/sample/real_world/SampleActivity.java +++ b/examples/real-world/src/main/java/com/soundcloud/lightcycle/sample/real_world/SampleActivity.java @@ -7,6 +7,7 @@ public class SampleActivity extends MyBaseActivity { @Inject @LightCycle ScreenTracker screenTracker; + @Inject @LightCycle AppForegroundStateProvider foregroundStateProvider; @Override public String getScreenName() { diff --git a/lightcycle-api/src/main/java/com/soundcloud/lightcycle/LightCycleBinder.java b/lightcycle-api/src/main/java/com/soundcloud/lightcycle/LightCycleBinder.java index 7c1f97b..1b86cba 100644 --- a/lightcycle-api/src/main/java/com/soundcloud/lightcycle/LightCycleBinder.java +++ b/lightcycle-api/src/main/java/com/soundcloud/lightcycle/LightCycleBinder.java @@ -1,6 +1,11 @@ package com.soundcloud.lightcycle; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; import android.util.Log; +import android.view.MenuItem; +import android.view.View; import java.lang.reflect.Method; @@ -43,4 +48,200 @@ private static Method findBinderForClass(Class cls) } return lightCycleInjectionMethod; } + + public static ActivityLightCycle lift(final ActivityLightCycle lightCycle) { + return new ActivityLightCycle() { + + @Override + public void onCreate(Target activity, Bundle bundle) { + lightCycle.onCreate(activity, bundle); + } + + @Override + public void onNewIntent(Target activity, Intent intent) { + lightCycle.onNewIntent(activity, intent); + } + + @Override + public void onStart(Target activity) { + lightCycle.onStart(activity); + } + + @Override + public void onResume(Target activity) { + lightCycle.onResume(activity); + } + + @Override + public boolean onOptionsItemSelected(Target activity, MenuItem item) { + return lightCycle.onOptionsItemSelected(activity, item); + } + + @Override + public void onPause(Target activity) { + lightCycle.onPause(activity); + } + + @Override + public void onStop(Target activity) { + lightCycle.onStop(activity); + } + + @Override + public void onSaveInstanceState(Target activity, Bundle bundle) { + lightCycle.onSaveInstanceState(activity, bundle); + } + + @Override + public void onRestoreInstanceState(Target activity, Bundle bundle) { + lightCycle.onRestoreInstanceState(activity, bundle); + } + + @Override + public void onDestroy(Target activity) { + lightCycle.onDestroy(activity); + } + }; + } + + public static FragmentLightCycle lift(final FragmentLightCycle lightCycle) { + return new FragmentLightCycle() { + + @Override + public void onAttach(Target fragment, Activity activity) { + lightCycle.onAttach(fragment, activity); + } + + @Override + public void onCreate(Target fragment, Bundle bundle) { + lightCycle.onCreate(fragment, bundle); + } + + @Override + public void onViewCreated(Target fragment, View view, Bundle savedInstanceState) { + lightCycle.onViewCreated(fragment, view, savedInstanceState); + } + + @Override + public void onStart(Target fragment) { + lightCycle.onStart(fragment); + } + + @Override + public void onResume(Target fragment) { + lightCycle.onResume(fragment); + } + + @Override + public boolean onOptionsItemSelected(Target fragment, MenuItem item) { + return lightCycle.onOptionsItemSelected(fragment, item); + } + + @Override + public void onPause(Target fragment) { + lightCycle.onPause(fragment); + } + + @Override + public void onStop(Target fragment) { + lightCycle.onStop(fragment); + } + + @Override + public void onSaveInstanceState(Target fragment, Bundle bundle) { + lightCycle.onSaveInstanceState(fragment, bundle); + } + + @Override + public void onRestoreInstanceState(Target fragment, Bundle bundle) { + lightCycle.onRestoreInstanceState(fragment, bundle); + } + + @Override + public void onDestroyView(Target fragment) { + lightCycle.onDestroyView(fragment); + } + + @Override + public void onDestroy(Target fragment) { + lightCycle.onDestroy(fragment); + } + + @Override + public void onDetach(Target fragment) { + lightCycle.onDetach(fragment); + } + }; + } + + + public static SupportFragmentLightCycle lift(final SupportFragmentLightCycle lightCycle) { + return new SupportFragmentLightCycle() { + + @Override + public void onAttach(Target fragment, Activity activity) { + lightCycle.onAttach(fragment, activity); + } + + @Override + public void onCreate(Target fragment, Bundle bundle) { + lightCycle.onCreate(fragment, bundle); + } + + @Override + public void onViewCreated(Target fragment, View view, Bundle savedInstanceState) { + lightCycle.onViewCreated(fragment, view, savedInstanceState); + } + + @Override + public void onStart(Target fragment) { + lightCycle.onStart(fragment); + } + + @Override + public void onResume(Target fragment) { + lightCycle.onResume(fragment); + } + + @Override + public boolean onOptionsItemSelected(Target fragment, MenuItem item) { + return lightCycle.onOptionsItemSelected(fragment, item); + } + + @Override + public void onPause(Target fragment) { + lightCycle.onPause(fragment); + } + + @Override + public void onStop(Target fragment) { + lightCycle.onStop(fragment); + } + + @Override + public void onSaveInstanceState(Target fragment, Bundle bundle) { + lightCycle.onSaveInstanceState(fragment, bundle); + } + + @Override + public void onRestoreInstanceState(Target fragment, Bundle bundle) { + lightCycle.onRestoreInstanceState(fragment, bundle); + } + + @Override + public void onDestroyView(Target fragment) { + lightCycle.onDestroyView(fragment); + } + + @Override + public void onDestroy(Target fragment) { + lightCycle.onDestroy(fragment); + } + + @Override + public void onDetach(Target fragment) { + lightCycle.onDetach(fragment); + } + }; + } } diff --git a/lightcycle-api/src/main/java/com/soundcloud/lightcycle/LightCycleDispatcher.java b/lightcycle-api/src/main/java/com/soundcloud/lightcycle/LightCycleDispatcher.java index 514869f..15d9841 100644 --- a/lightcycle-api/src/main/java/com/soundcloud/lightcycle/LightCycleDispatcher.java +++ b/lightcycle-api/src/main/java/com/soundcloud/lightcycle/LightCycleDispatcher.java @@ -1,5 +1,6 @@ package com.soundcloud.lightcycle; +// TODO : rename ? public interface LightCycleDispatcher { void bind(LightCycle lightCycle); diff --git a/lightcycle-processor/src/main/java/com/soundcloud/lightcycle/LightCycleProcessor.java b/lightcycle-processor/src/main/java/com/soundcloud/lightcycle/LightCycleProcessor.java index 36bdd93..9d1ad50 100644 --- a/lightcycle-processor/src/main/java/com/soundcloud/lightcycle/LightCycleProcessor.java +++ b/lightcycle-processor/src/main/java/com/soundcloud/lightcycle/LightCycleProcessor.java @@ -16,6 +16,7 @@ import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; import java.io.IOException; @@ -33,14 +34,20 @@ public class LightCycleProcessor extends AbstractProcessor { private static final String LIB_PACKAGE = "com.soundcloud.lightcycle"; private static final String ANNOTATION_CLASS = LIB_PACKAGE + ".LightCycle"; - private static final String BINDER_CLASS_NAME = "LightCycleBinder"; - private static final String BINDER_CLASS = LIB_PACKAGE + "." + BINDER_CLASS_NAME; + private static final String CLASS_BINDER_NAME = "LightCycleBinder"; + private static final String METHOD_BIND_NAME = "bind"; + private static final String METHOD_BIND_ARGUMENT_NAME = "target"; + private static final String METHOD_LIFT_NAME = "com.soundcloud.lightcycle.LightCycleBinder.lift"; + private static final String INTERFACE_DISPATCHER_NAME = "LightCycleDispatcher"; + private Elements elementUtils; + private Types typeUtils; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); + typeUtils = processingEnv.getTypeUtils(); elementUtils = processingEnv.getElementUtils(); } @@ -54,7 +61,7 @@ public boolean process(Set annotations, RoundEnvironment verifyFieldsAccessible(annotatedFields); - log("processing " + annotatedFields.size() + " fields"); + note("processing " + annotatedFields.size() + " fields"); Map> lightCyclesByHostElement = new HashMap<>(); Set erasedTargetNames = new HashSet<>(); @@ -86,7 +93,7 @@ private void generateBinder(Set erasedTargetNames, List erasedTargetNames, List erasedTargetNames, List elements, Element hostElement, JavaWriter writer) throws IOException { writer.emitEmptyLine(); final String hostClass = hostElement.getSimpleName().toString(); - writer.beginMethod("void", "bind", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), hostClass, "target"); + writer.beginMethod("void", METHOD_BIND_NAME, EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), hostClass, METHOD_BIND_ARGUMENT_NAME); emitBindParent(erasedTargetNames, hostElement, writer); - emitBindLightCycles(elements, writer); + emitBindLightCycles(hostElement, elements, writer); writer.endMethod(); } - private void emitBindLightCycles(List elements, JavaWriter writer) throws IOException { - for (Element element : elements) { - writer.emitStatement("target.bind(target.%s)", element.getSimpleName()); + private void emitBindLightCycles(Element hostElement, List elements, JavaWriter writer) throws IOException { + final TypeMirror dispatchedType = getDispatchedType((TypeElement) hostElement); + if (dispatchedType == null) { + error(hostElement, "Could not find the dispatcher. Class may implement " + INTERFACE_DISPATCHER_NAME); + } else { + for (Element element : elements) { + final String liftedName = element.getSimpleName() + "$Lifted"; + + writer.emitStatement("final %s %s = %s(%s.%s)", + dispatchedType.toString(), + liftedName, + METHOD_LIFT_NAME, + METHOD_BIND_ARGUMENT_NAME, + element.getSimpleName()); + writer.emitStatement("%s.%s(%s)", METHOD_BIND_ARGUMENT_NAME, METHOD_BIND_NAME, liftedName); + } } } + private TypeMirror getDispatchedType(TypeElement hostElement) { + TypeElement typeElement = hostElement; + TypeMirror type = hostElement.asType(); + + for (; type.getKind() != TypeKind.NONE; ) { + for (TypeMirror anInterface : typeElement.getInterfaces()) { + final Element element = typeUtils.asElement(anInterface); + if (element.getSimpleName().contentEquals(INTERFACE_DISPATCHER_NAME)) { + return ((DeclaredType) anInterface).getTypeArguments().get(0); + } + } + typeElement = (TypeElement) ((DeclaredType) type).asElement(); + type = typeElement.getSuperclass(); + } + return null; + } + private void emitBindParent(Set erasedTargetNames, Element hostElement, JavaWriter writer) throws IOException { final TypeElement typeElement = (TypeElement) hostElement; String parentName = findParent(erasedTargetNames, typeElement); if (parentName != null) { - writer.emitStatement(getBinderName(parentName) + ".bind(target)"); + writer.emitStatement(getBinderName(parentName) + ".%s(%s)", METHOD_BIND_NAME, METHOD_BIND_ARGUMENT_NAME); } } @@ -170,7 +207,18 @@ private void verifyFieldsAccessible(Set elements) { } } - private void log(String message) { + private void note(String message) { processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "LightCycleProcessor: " + message); } + + private void error(Element element, String message, Object... args) { + log(Diagnostic.Kind.ERROR, element, message, args); + } + + private void log(Diagnostic.Kind error, Element element, String message, Object[] args) { + if (args.length > 0) { + message = String.format(message, args); + } + processingEnv.getMessager().printMessage(error, message, element); + } } diff --git a/lightcycle-processor/src/test/java/com/soundcloud/lightcycle/LightCycleProcessorTest.java b/lightcycle-processor/src/test/java/com/soundcloud/lightcycle/LightCycleProcessorTest.java index 8f5e84c..6a36719 100644 --- a/lightcycle-processor/src/test/java/com/soundcloud/lightcycle/LightCycleProcessorTest.java +++ b/lightcycle-processor/src/test/java/com/soundcloud/lightcycle/LightCycleProcessorTest.java @@ -19,8 +19,10 @@ public class LightCycleProcessorTest { "public final class ValidTestFragment$LightCycleBinder {", "", " public static void bind(ValidTestFragment target) {", - " target.bind(target.lightCycle1);", - " target.bind(target.lightCycle2);", + " final com.soundcloud.lightcycle.FragmentLightCycle lightCycle1$Lifted = com.soundcloud.lightcycle.LightCycleBinder.lift(target.lightCycle1);", + " target.bind(lightCycle1$Lifted);", + " final com.soundcloud.lightcycle.FragmentLightCycle lightCycle2$Lifted = com.soundcloud.lightcycle.LightCycleBinder.lift(target.lightCycle2);", + " target.bind(lightCycle2$Lifted);", " }", "}"); @@ -31,8 +33,10 @@ public class LightCycleProcessorTest { "public final class ValidTestSupportFragment$LightCycleBinder {", "", " public static void bind(ValidTestSupportFragment target) {", - " target.bind(target.lightCycle1);", - " target.bind(target.lightCycle2);", + " final com.soundcloud.lightcycle.SupportFragmentLightCycle lightCycle1$Lifted = com.soundcloud.lightcycle.LightCycleBinder.lift(target.lightCycle1);", + " target.bind(lightCycle1$Lifted);", + " final com.soundcloud.lightcycle.SupportFragmentLightCycle lightCycle2$Lifted = com.soundcloud.lightcycle.LightCycleBinder.lift(target.lightCycle2);", + " target.bind(lightCycle2$Lifted);", " }", "}"); @@ -43,8 +47,23 @@ public class LightCycleProcessorTest { "public final class ValidTestActivity$LightCycleBinder {", "", " public static void bind(ValidTestActivity target) {", - " target.bind(target.lightCycle1);", - " target.bind(target.lightCycle2);", + " final com.soundcloud.lightcycle.ActivityLightCycle lightCycle1$Lifted = com.soundcloud.lightcycle.LightCycleBinder.lift(target.lightCycle1);", + " target.bind(lightCycle1$Lifted);", + " final com.soundcloud.lightcycle.ActivityLightCycle lightCycle2$Lifted = com.soundcloud.lightcycle.LightCycleBinder.lift(target.lightCycle2);", + " target.bind(lightCycle2$Lifted);", + " }", + "}"); + + private static final String ACTIVITY_HIERARCHY_BINDER_SRC = Joiner.on("\n").join( + "package com.test;", + "", + "", + "public final class ValidTestHierarchyActivity$LightCycleBinder {", + "", + " public static void bind(ValidTestHierarchyActivity target) {", + " com.test.BaseActivity$LightCycleBinder.bind(target);", + " final com.soundcloud.lightcycle.ActivityLightCycle lightCycle2$Lifted = com.soundcloud.lightcycle.LightCycleBinder.lift(target.lightCycle2);", + " target.bind(lightCycle2$Lifted);", " }", "}"); @@ -78,6 +97,16 @@ public void shouldGenerateInjectorForActivity() { .and().generatesSources(expectedSource); } + @Test + public void shouldGenerateInjectorForActivityHierarchy() { + JavaFileObject expectedSource = forSourceString("com.test.ValidTestHierarchyActivity$LightCycleBinder", ACTIVITY_HIERARCHY_BINDER_SRC); + Truth.ASSERT.about(javaSource()) + .that(JavaFileObjects.forResource("com/test/ValidTestHierarchyActivity.java")) + .processedWith(new LightCycleProcessor()) + .compilesWithoutError() + .and().generatesSources(expectedSource); + } + //TODO: make this test more specific with a TestRule to catch false positives @Test(expected = RuntimeException.class) public void shouldThrowExceptionWhenLightCycleFieldIsPrivate() { diff --git a/lightcycle-processor/src/test/resources/com/test/ValidTestActivity.java b/lightcycle-processor/src/test/resources/com/test/ValidTestActivity.java index 5e90fd7..96fa06f 100644 --- a/lightcycle-processor/src/test/resources/com/test/ValidTestActivity.java +++ b/lightcycle-processor/src/test/resources/com/test/ValidTestActivity.java @@ -7,13 +7,13 @@ import android.app.Activity; -public class ValidTestActivity extends Activity implements LightCycleDispatcher { +public class ValidTestActivity extends Activity implements LightCycleDispatcher> { @LightCycle LightCycle1 lightCycle1; @LightCycle LightCycle2 lightCycle2; @Override - public void bind(ActivityLightCycle lightCycle) { + public void bind(ActivityLightCycle lightCycle) { // nop } diff --git a/lightcycle-processor/src/test/resources/com/test/ValidTestFragment.java b/lightcycle-processor/src/test/resources/com/test/ValidTestFragment.java index 21683cd..88c1f85 100644 --- a/lightcycle-processor/src/test/resources/com/test/ValidTestFragment.java +++ b/lightcycle-processor/src/test/resources/com/test/ValidTestFragment.java @@ -8,13 +8,13 @@ import android.app.Fragment; -public class ValidTestFragment extends Fragment implements LightCycleDispatcher { +public class ValidTestFragment extends Fragment implements LightCycleDispatcher> { @LightCycle LightCycle1 lightCycle1; @LightCycle LightCycle2 lightCycle2; @Override - public void bind(FragmentLightCycle lightCycle) { + public void bind(FragmentLightCycle lightCycle) { // nop } diff --git a/lightcycle-processor/src/test/resources/com/test/ValidTestHierarchyActivity.java b/lightcycle-processor/src/test/resources/com/test/ValidTestHierarchyActivity.java new file mode 100644 index 0000000..b8306cc --- /dev/null +++ b/lightcycle-processor/src/test/resources/com/test/ValidTestHierarchyActivity.java @@ -0,0 +1,30 @@ +package com.test; + +import com.soundcloud.lightcycle.ActivityLightCycle; +import com.soundcloud.lightcycle.DefaultActivityLightCycle; +import com.soundcloud.lightcycle.LightCycle; +import com.soundcloud.lightcycle.LightCycleDispatcher; + +import android.app.Activity; + +public class ValidTestHierarchyActivity extends BaseActivity { + @LightCycle LightCycle2 lightCycle2; + +} + +class BaseActivity extends Activity implements LightCycleDispatcher> { + + @LightCycle LightCycle1 lightCycle1; + + @Override + public void bind(ActivityLightCycle lightCycle) { + // nop + } + +} + +class LightCycle1 extends DefaultActivityLightCycle { +} + +class LightCycle2 extends DefaultActivityLightCycle { +} diff --git a/lightcycle-processor/src/test/resources/com/test/ValidTestSupportFragment.java b/lightcycle-processor/src/test/resources/com/test/ValidTestSupportFragment.java index 3c14450..33a76f9 100644 --- a/lightcycle-processor/src/test/resources/com/test/ValidTestSupportFragment.java +++ b/lightcycle-processor/src/test/resources/com/test/ValidTestSupportFragment.java @@ -7,20 +7,20 @@ import android.support.v4.app.Fragment; -public class ValidTestSupportFragment extends Fragment implements LightCycleDispatcher { +public class ValidTestSupportFragment extends Fragment implements LightCycleDispatcher> { @LightCycle LightCycle1 lightCycle1; @LightCycle LightCycle2 lightCycle2; @Override - public void bind(SupportFragmentLightCycle lightCycle) { + public void bind(SupportFragmentLightCycle lightCycle) { // nop } } -class LightCycle1 extends DefaultSupportFragmentLightCycle { +class LightCycle1 extends DefaultSupportFragmentLightCycle { } -class LightCycle2 extends DefaultSupportFragmentLightCycle { +class LightCycle2 extends DefaultSupportFragmentLightCycle { } diff --git a/lightcycle-sample/src/main/java/com/soundcloud/lightcycle/sample/MyBaseActivity.java b/lightcycle-sample/src/main/java/com/soundcloud/lightcycle/sample/MyBaseActivity.java new file mode 100644 index 0000000..2f2d4a0 --- /dev/null +++ b/lightcycle-sample/src/main/java/com/soundcloud/lightcycle/sample/MyBaseActivity.java @@ -0,0 +1,96 @@ +package com.soundcloud.lightcycle.sample; + +import com.soundcloud.lightcycle.ActivityLightCycle; +import com.soundcloud.lightcycle.ActivityLightCycleDispatcher; +import com.soundcloud.lightcycle.LightCycleBinder; +import com.soundcloud.lightcycle.LightCycleDispatcher; +import com.soundcloud.lightcycle.sample.tracker.Screen; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.MenuItem; + +// Implement you base activity to wire things up or use one of the provide default activities (like LightCycleAppCompatActivity). +public abstract class MyBaseActivity extends AppCompatActivity + implements Screen, LightCycleDispatcher> { + private final ActivityLightCycleDispatcher lightCycleDispatcher; + + public MyBaseActivity() { + lightCycleDispatcher = new ActivityLightCycleDispatcher<>(); + SampleApp.getObjectGraph().inject(this); + } + + public void liftAndBind(ActivityLightCycle lightCycle) { + bind(LightCycleBinder.lift(lightCycle)); + } + + @Override + public void bind(ActivityLightCycle lightCycle) { + lightCycleDispatcher.bind(lightCycle); + } + + abstract void setActivityContentView(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setActivityContentView(); + LightCycleBinder.bind(this); + lightCycleDispatcher.onCreate(this, savedInstanceState); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + lightCycleDispatcher.onNewIntent(this, intent); + } + + @Override + protected void onStart() { + super.onStart(); + lightCycleDispatcher.onStart(this); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + return lightCycleDispatcher.onOptionsItemSelected(this, item); + } + + @Override + protected void onStop() { + lightCycleDispatcher.onStop(this); + super.onStop(); + } + + @Override + protected void onResume() { + super.onResume(); + lightCycleDispatcher.onResume(this); + } + + @Override + protected void onPause() { + lightCycleDispatcher.onPause(this); + super.onPause(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + lightCycleDispatcher.onSaveInstanceState(this, outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + lightCycleDispatcher.onRestoreInstanceState(this, savedInstanceState); + } + + @Override + protected void onDestroy() { + lightCycleDispatcher.onDestroy(this); + super.onDestroy(); + } +} diff --git a/lightcycle-sample/src/main/java/com/soundcloud/lightcycle/sample/SampleActivity.java b/lightcycle-sample/src/main/java/com/soundcloud/lightcycle/sample/SampleActivity.java new file mode 100644 index 0000000..e0b75d8 --- /dev/null +++ b/lightcycle-sample/src/main/java/com/soundcloud/lightcycle/sample/SampleActivity.java @@ -0,0 +1,25 @@ +package com.soundcloud.lightcycle.sample; + +import com.soundcloud.lightcycle.LightCycle; +import com.soundcloud.lightcycle.sample.tracker.ScreenTracker; + +import javax.inject.Inject; + +public class SampleActivity extends MyBaseActivity { + @Inject @LightCycle ScreenTracker screenTracker; + @Inject AppForegroundStateProvider foregroundStateProvider; + + public SampleActivity() { + liftAndBind(foregroundStateProvider); + } + + @Override + public String getScreenName() { + return "SampleScreenName"; + } + + @Override + void setActivityContentView() { + setContentView(R.layout.activity_sample); + } +}