├── sample
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ └── strings.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ └── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ ├── java
│ │ │ └── ru
│ │ │ │ └── noties
│ │ │ │ └── handle
│ │ │ │ └── sample
│ │ │ │ ├── StickyThatIsNotCancelledEvent.java
│ │ │ │ ├── StickyEvent.java
│ │ │ │ ├── MainApp.java
│ │ │ │ ├── BaseActivity.java
│ │ │ │ ├── NotParcelableObject.java
│ │ │ │ └── MainActivity.java
│ │ └── AndroidManifest.xml
│ └── androidTest
│ │ └── java
│ │ └── ru
│ │ └── noties
│ │ └── handle
│ │ └── ApplicationTest.java
├── proguard-rules.pro
└── build.gradle
├── handle-benchmark
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── styles.xml
│ │ │ │ └── dimens.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── menu
│ │ │ │ └── menu_main.xml
│ │ │ └── layout
│ │ │ │ └── activity_main.xml
│ │ ├── java
│ │ │ └── ru
│ │ │ │ └── noties
│ │ │ │ └── handle
│ │ │ │ └── benchmark
│ │ │ │ ├── base
│ │ │ │ ├── EventReceiver.java
│ │ │ │ ├── BenchmarkParams.java
│ │ │ │ ├── IEventBus.java
│ │ │ │ ├── AbsBenchmarkRunnable.java
│ │ │ │ ├── BenchmarkRunnable.java
│ │ │ │ └── subjects
│ │ │ │ │ ├── GreenRobotEventBus.java
│ │ │ │ │ └── HandleEventBus.java
│ │ │ │ └── MainActivity.java
│ │ └── AndroidManifest.xml
│ └── androidTest
│ │ └── java
│ │ └── ru
│ │ └── noties
│ │ └── handle
│ │ └── benchmark
│ │ └── ApplicationTest.java
├── proguard-rules.pro
└── build.gradle
├── handle-library
├── .gitignore
├── src
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── ru
│ │ │ └── noties
│ │ │ └── handle
│ │ │ ├── IEventHandler.java
│ │ │ ├── events
│ │ │ ├── StickyEventNotUsedEvent.java
│ │ │ ├── NoEventHandlerEvent.java
│ │ │ └── OnDispatchExceptionEvent.java
│ │ │ ├── HandleHandler.java
│ │ │ └── Handle.java
│ └── androidTest
│ │ └── java
│ │ └── ru
│ │ └── noties
│ │ └── handle
│ │ └── ApplicationTest.java
├── build.gradle
└── proguard-rules.pro
├── handle-processor
├── .gitignore
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── services
│ │ │ └── javax.annotation.processing.Processor
│ │ └── java
│ │ └── ru
│ │ └── noties
│ │ └── handle
│ │ └── processor
│ │ ├── Logger.java
│ │ ├── parser
│ │ ├── EventHandlerHolder.java
│ │ └── EventHandlerParser.java
│ │ ├── writer
│ │ ├── Indent.java
│ │ └── EventHandlerWriter.java
│ │ └── HandleProcessor.java
└── build.gradle
├── handle-annotations
├── .gitignore
├── build.gradle
└── src
│ └── main
│ └── java
│ └── ru
│ └── noties
│ └── handle
│ └── annotations
│ └── EventHandler.java
├── handle-library-test
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ └── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ └── AndroidManifest.xml
│ └── androidTest
│ │ └── java
│ │ └── ru
│ │ └── noties
│ │ └── handle
│ │ ├── HandleMediator.java
│ │ └── test
│ │ ├── ApplicationTest.java
│ │ ├── AllTests.java
│ │ └── HandleTest.java
├── build.gradle
└── proguard-rules.pro
├── settings.gradle
├── .gitignore
├── gradle_maven_jar_publish.gradle
├── README.md
└── LICENSE
/sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/handle-benchmark/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/handle-library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/handle-processor/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/handle-annotations/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/handle-library-test/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Handle
3 |
4 |
--------------------------------------------------------------------------------
/handle-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor:
--------------------------------------------------------------------------------
1 | ru.noties.handle.processor.HandleProcessor
--------------------------------------------------------------------------------
/handle-library-test/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | HandleTest
3 |
4 |
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/sample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/sample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/sample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':sample', ':handle-library', ':handle-processor', ':handle-annotations', ':handle-library-test', ':handle-benchmark'
2 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/handle-benchmark/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/handle-benchmark/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/handle-benchmark/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/handle-benchmark/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/handle-benchmark/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/handle-benchmark/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/handle-benchmark/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/handle-annotations/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply from: '../gradle_maven_jar_publish.gradle'
3 |
4 | sourceCompatibility = 1.7
5 | targetCompatibility = 1.7
--------------------------------------------------------------------------------
/handle-library-test/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/handle-library-test/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/handle-library-test/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/handle-library-test/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/handle-library-test/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/handle-library-test/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/handle-library-test/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noties/Handle/HEAD/handle-library-test/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/handle-library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/handle-library-test/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/sample/src/main/java/ru/noties/handle/sample/StickyThatIsNotCancelledEvent.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.sample;
2 |
3 | /**
4 | * Created by Dimitry Ivanov on 23.07.2015.
5 | */
6 | public class StickyThatIsNotCancelledEvent {
7 | }
8 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Benchmark
3 |
4 | Hello world!
5 | Settings
6 |
7 |
--------------------------------------------------------------------------------
/handle-processor/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 |
3 | sourceCompatibility = 1.7
4 | targetCompatibility = 1.7
5 |
6 | dependencies {
7 | compile project(':handle-annotations')
8 | }
9 |
10 | apply from: '../gradle_maven_jar_publish.gradle'
--------------------------------------------------------------------------------
/handle-benchmark/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/handle-library/src/main/java/ru/noties/handle/IEventHandler.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle;
2 |
3 | /**
4 | * Created by Dimitry Ivanov on 21.07.2015.
5 | */
6 | public interface IEventHandler {
7 | void onEvent(Object event);
8 | boolean isEventRegistered(Class> cl);
9 | }
10 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/java/ru/noties/handle/benchmark/base/EventReceiver.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.benchmark.base;
2 |
3 | /**
4 | * Created by Dimitry Ivanov on 02.09.2015.
5 | */
6 | public interface EventReceiver {
7 |
8 | interface OnComplete {
9 | void apply();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/handle-processor/src/main/java/ru/noties/handle/processor/Logger.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.processor;
2 |
3 | import javax.tools.Diagnostic;
4 |
5 | /**
6 | * Created by Dimitry Ivanov on 21.07.2015.
7 | */
8 | public interface Logger {
9 | void log(Diagnostic.Kind level, String message, Object... args);
10 | }
11 |
--------------------------------------------------------------------------------
/handle-library-test/src/androidTest/java/ru/noties/handle/HandleMediator.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle;
2 |
3 | /**
4 | * Created by Dimitry Ivanov on 03.08.2015.
5 | */
6 | public class HandleMediator {
7 |
8 | private HandleMediator() {}
9 |
10 | public static void clear() {
11 | Handle.clear();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/sample/src/main/java/ru/noties/handle/sample/StickyEvent.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.sample;
2 |
3 | /**
4 | * Created by Dimitry Ivanov on 22.07.2015.
5 | */
6 | public class StickyEvent {
7 |
8 | private final String text;
9 |
10 | public StickyEvent(String text) {
11 | this.text = text;
12 | }
13 |
14 | public String getText() {
15 | return text;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/handle-library-test/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/java/ru/noties/handle/benchmark/base/BenchmarkParams.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.benchmark.base;
2 |
3 | /**
4 | * Created by Dimitry Ivanov on 02.09.2015.
5 | */
6 | public class BenchmarkParams {
7 |
8 | final int subscribers;
9 | final int events;
10 |
11 | public BenchmarkParams(int subscribers, int events) {
12 | this.subscribers = subscribers;
13 | this.events = events;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/sample/src/androidTest/java/ru/noties/handle/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/handle-library/src/androidTest/java/ru/noties/handle/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/handle-benchmark/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/handle-library-test/src/androidTest/java/ru/noties/handle/test/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.test;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/handle-benchmark/src/androidTest/java/ru/noties/handle/benchmark/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.benchmark;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/handle-library/src/main/java/ru/noties/handle/events/StickyEventNotUsedEvent.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.events;
2 |
3 | /**
4 | * Created by Dimitry Ivanov on 23.07.2015.
5 | */
6 | public final class StickyEventNotUsedEvent {
7 |
8 | private final Object stickyEvent;
9 |
10 | public StickyEventNotUsedEvent(Object stickyEvent) {
11 | this.stickyEvent = stickyEvent;
12 | }
13 |
14 | public Object getStickyEvent() {
15 | return stickyEvent;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/sample/src/main/java/ru/noties/handle/sample/MainApp.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.sample;
2 |
3 | import android.app.Application;
4 |
5 | import ru.noties.debug.Debug;
6 | import ru.noties.debug.out.AndroidLogDebugOutput;
7 |
8 | /**
9 | * Created by Dimitry Ivanov on 21.07.2015.
10 | */
11 | public class MainApp extends Application {
12 |
13 | @Override
14 | public void onCreate() {
15 | super.onCreate();
16 |
17 | Debug.init(new AndroidLogDebugOutput(BuildConfig.DEBUG));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/java/ru/noties/handle/benchmark/base/IEventBus.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.benchmark.base;
2 |
3 | /**
4 | * Created by Dimitry Ivanov on 02.09.2015.
5 | */
6 | public interface IEventBus {
7 |
8 | String getName();
9 |
10 | void init();
11 |
12 | void register(Object object);
13 | void unregister(Object object);
14 | void post(Object object);
15 |
16 | Object newEvent();
17 |
18 | EventReceiver getEventReceiver(int expected, EventReceiver.OnComplete onComplete);
19 | }
20 |
--------------------------------------------------------------------------------
/handle-library-test/src/androidTest/java/ru/noties/handle/test/AllTests.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.test;
2 |
3 | import android.test.suitebuilder.TestSuiteBuilder;
4 |
5 | import junit.framework.Test;
6 | import junit.framework.TestSuite;
7 |
8 | /**
9 | * Created by Dimitry Ivanov on 03.08.2015.
10 | */
11 | public class AllTests extends TestSuite {
12 |
13 | public static Test suite() {
14 | return new TestSuiteBuilder(AllTests.class)
15 | .includeAllPackagesUnderHere()
16 | .build();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/handle-annotations/src/main/java/ru/noties/handle/annotations/EventHandler.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.annotations;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Main annotation with Events classes that should be included in generated IEventHandler
10 | * Created by Dimitry Ivanov on 21.07.2015.
11 | */
12 | @Target(ElementType.TYPE)
13 | @Retention(RetentionPolicy.CLASS)
14 | public @interface EventHandler {
15 | Class>[] value();
16 | }
17 |
--------------------------------------------------------------------------------
/handle-processor/src/main/java/ru/noties/handle/processor/parser/EventHandlerHolder.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.processor.parser;
2 |
3 | import java.util.List;
4 |
5 | import javax.lang.model.element.TypeElement;
6 |
7 | /**
8 | * Created by Dimitry Ivanov on 21.07.2015.
9 | */
10 | public class EventHandlerHolder {
11 |
12 | public final TypeElement element;
13 | public final List eventClasses;
14 |
15 | EventHandlerHolder(TypeElement element, List eventClasses) {
16 | this.element = element;
17 | this.eventClasses = eventClasses;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/handle-library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "22.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 8
9 | targetSdkVersion 22
10 | versionCode 1
11 | versionName "1.0.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | apply from: 'https://raw.githubusercontent.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle'
22 |
--------------------------------------------------------------------------------
/handle-library/src/main/java/ru/noties/handle/events/NoEventHandlerEvent.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.events;
2 |
3 | /**
4 | * This event will be posted when no event handler was found to handle a certain event.
5 | * Contains event that was not delivered to any {@link ru.noties.handle.IEventHandler}
6 | * Created by Dimitry Ivanov on 21.07.2015.
7 | */
8 | public final class NoEventHandlerEvent {
9 |
10 | private final Object event;
11 |
12 | public NoEventHandlerEvent(Object event) {
13 | this.event = event;
14 | }
15 |
16 | public Object getEvent() {
17 | return event;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/handle-library-test/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "22.0.1"
6 |
7 | defaultConfig {
8 | applicationId "ru.noties.handle.test"
9 | minSdkVersion 14
10 | targetSdkVersion 22
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile project(':handle-library')
24 | }
25 |
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/sample/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/handle-benchmark/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/handle-library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/handle-library-test/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea
4 | .DS_Store
5 |
6 | /gradle
7 | gradlew
8 | gradlew.bat
9 |
10 | **/build
11 |
12 | *.iml
13 |
14 | # built application files
15 | *.apk
16 | *.ap_
17 |
18 | # files for the dex VM
19 | *.dex
20 |
21 | # Java class files
22 | *.class
23 |
24 | # generated files
25 | bin/
26 | gen/
27 | build/
28 |
29 | # Local configuration file (sdk path, etc)
30 | local.properties
31 |
32 | # gradle properties with signing config
33 | gradle.properties
34 |
35 | # Project configuration file (target-sdk-version)
36 | .DS_Store
37 | project.properties
38 | out
39 |
40 | # Eclipse project files
41 | .classpath
42 | .project
43 |
44 | # Proguard folder generated by Eclipse
45 | proguard/
46 |
47 | # Intellij project files
48 | *.iml
49 | *.ipr
50 | *.iws
51 | .idea/
52 | .gradle/
--------------------------------------------------------------------------------
/handle-benchmark/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.0"
6 |
7 | defaultConfig {
8 | applicationId "ru.noties.handle.benchmark"
9 | minSdkVersion 14
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | compile 'com.android.support:appcompat-v7:23.0.0'
25 | compile 'ru.noties.handle:core:1.0.0'
26 | compile 'ru.noties:debug:2.0.1'
27 | compile 'de.greenrobot:eventbus:2.4.0'
28 | }
29 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/handle-library/src/main/java/ru/noties/handle/events/OnDispatchExceptionEvent.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.events;
2 |
3 | /**
4 | * This event will be posted when {@link ru.noties.handle.IEventHandler} threw an Exception
5 | * during onEvent method execution
6 | * Created by Dimitry Ivanov on 21.07.2015.
7 | */
8 | public final class OnDispatchExceptionEvent {
9 |
10 | private final Class> eventHandler;
11 | private final Object event;
12 | private final Throwable throwable;
13 |
14 | public OnDispatchExceptionEvent(Class> eventHandler, Object event, Throwable throwable) {
15 | this.eventHandler = eventHandler;
16 | this.event = event;
17 | this.throwable = throwable;
18 | }
19 |
20 | public Class> getEventHandler() {
21 | return eventHandler;
22 | }
23 |
24 | public Object getEvent() {
25 | return event;
26 | }
27 |
28 | public Throwable getThrowable() {
29 | return throwable;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'com.neenbedankt.android-apt'
3 |
4 | buildscript {
5 | repositories {
6 | mavenCentral()
7 | }
8 |
9 | dependencies {
10 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.5.1'
11 | }
12 | }
13 |
14 | android {
15 | compileSdkVersion 22
16 | buildToolsVersion "22.0.1"
17 |
18 | defaultConfig {
19 | applicationId "ru.noties.handle.sample"
20 | minSdkVersion 8
21 | targetSdkVersion 22
22 | versionCode 1
23 | versionName "1.0"
24 | }
25 | buildTypes {
26 | release {
27 | minifyEnabled false
28 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
29 | }
30 | }
31 | }
32 |
33 | dependencies {
34 | compile 'ru.noties:debug:2.0.0'
35 | compile project(':handle-library')
36 | compile project(':handle-annotations')
37 | apt project(':handle-processor')
38 | }
39 |
--------------------------------------------------------------------------------
/handle-processor/src/main/java/ru/noties/handle/processor/writer/Indent.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.processor.writer;
2 |
3 | import java.util.Arrays;
4 |
5 | /**
6 | * Created by Dimitry Ivanov on 15.07.2015.
7 | */
8 | public class Indent {
9 |
10 | private int length;
11 | private String cached;
12 |
13 | public Indent increment() {
14 | length++;
15 | cached = null;
16 | return this;
17 | }
18 |
19 | public Indent decrement() {
20 | length--;
21 | cached = null;
22 | return this;
23 | }
24 |
25 | public Indent setLength(int length) {
26 | if (this.length != length) {
27 | this.length = length;
28 | cached = null;
29 | }
30 | return this;
31 | }
32 |
33 | @Override
34 | public String toString() {
35 | if (cached == null) {
36 | cached = createCache(length);
37 | }
38 | return cached;
39 | }
40 |
41 | static String createCache(int length) {
42 | if (length == 0) {
43 | return "";
44 | }
45 | final char[] chars = new char[4 * length];
46 | Arrays.fill(chars, ' ');
47 | return new String(chars);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/java/ru/noties/handle/benchmark/base/AbsBenchmarkRunnable.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.benchmark.base;
2 |
3 | import android.os.SystemClock;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | import ru.noties.debug.Debug;
9 |
10 | /**
11 | * Created by Dimitry Ivanov on 02.09.2015.
12 | */
13 | public abstract class AbsBenchmarkRunnable implements Runnable {
14 |
15 | private final List- mItems = new ArrayList<>();
16 |
17 | private long mStart;
18 |
19 | protected void start() {
20 | mStart = SystemClock.elapsedRealtime();
21 | }
22 |
23 | protected void end(String message, Object... args) {
24 | final long end = SystemClock.elapsedRealtime();
25 | mItems.add(new Item(
26 | String.format(message, args),
27 | end - mStart
28 | ));
29 | }
30 |
31 | public List
- getItems() {
32 | return mItems;
33 | }
34 |
35 | protected void printResults() {
36 | Debug.i("######################################################");
37 | for (Item item: mItems) {
38 | Debug.i("%s, %d ms", item.message, item.time);
39 | }
40 | Debug.i("######################################################");
41 | }
42 |
43 | public static class Item {
44 |
45 | private final String message;
46 | private final long time;
47 |
48 | Item(String message, long time) {
49 | this.message = message;
50 | this.time = time;
51 | }
52 |
53 | public String getMessage() {
54 | return message;
55 | }
56 |
57 | public long getTime() {
58 | return time;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/sample/src/main/java/ru/noties/handle/sample/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.sample;
2 |
3 | import android.app.Activity;
4 |
5 | import ru.noties.debug.Debug;
6 | import ru.noties.handle.Handle;
7 | import ru.noties.handle.IEventHandler;
8 | import ru.noties.handle.events.NoEventHandlerEvent;
9 | import ru.noties.handle.events.OnDispatchExceptionEvent;
10 | import ru.noties.handle.events.StickyEventNotUsedEvent;
11 | import ru.noties.handle.annotations.EventHandler;
12 |
13 | /**
14 | * Created by Dimitry Ivanov on 21.07.2015.
15 | */
16 | @EventHandler({ OnDispatchExceptionEvent.class, NoEventHandlerEvent.class, StickyEventNotUsedEvent.class})
17 | public class BaseActivity extends Activity {
18 |
19 | private final IEventHandler mHandler = new BaseActivityEventHandler() {
20 | @Override
21 | public void onEvent(OnDispatchExceptionEvent event) {
22 | Debug.e(event.getThrowable(), "Handler: %s, event: %s", event.getEventHandler(), event.getEvent());
23 | }
24 |
25 | @Override
26 | public void onEvent(NoEventHandlerEvent event) {
27 | Debug.i("noEventHandler: %s", event.getEvent());
28 | }
29 |
30 | @Override
31 | public void onEvent(StickyEventNotUsedEvent event) {
32 | final Object sticky = event.getStickyEvent();
33 | Debug.i("sticky no used, removing, sticky: %s", sticky);
34 | Handle.cancelSticky(sticky);
35 | }
36 | };
37 |
38 | @Override
39 | public void onStart() {
40 | super.onStart();
41 |
42 | Handle.register(mHandler);
43 | }
44 |
45 | @Override
46 | public void onStop() {
47 | super.onStop();
48 |
49 | Handle.unregister(mHandler);
50 | }
51 |
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/handle-processor/src/main/java/ru/noties/handle/processor/parser/EventHandlerParser.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.processor.parser;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import javax.lang.model.element.TypeElement;
7 | import javax.lang.model.type.MirroredTypesException;
8 | import javax.lang.model.type.TypeMirror;
9 |
10 | import ru.noties.handle.processor.Logger;
11 |
12 | /**
13 | * Created by Dimitry Ivanov on 21.07.2015.
14 | */
15 | public class EventHandlerParser {
16 |
17 | private final Logger mLogger;
18 |
19 | public EventHandlerParser(Logger logger) {
20 | this.mLogger = logger;
21 | }
22 |
23 | public EventHandlerHolder parse(TypeElement element) {
24 | final ru.noties.handle.annotations.EventHandler eventHandler = element.getAnnotation(ru.noties.handle.annotations.EventHandler.class);
25 | if (eventHandler == null) {
26 | return null;
27 | }
28 |
29 | final List events = new ArrayList<>();
30 |
31 | try {
32 | final Class>[] classes = eventHandler.value();
33 | for (Class> c: classes) {
34 | events.add(c.getCanonicalName());
35 | }
36 | } catch (MirroredTypesException e) {
37 | final List extends TypeMirror> typeMirrors = e.getTypeMirrors();
38 | if (typeMirrors != null
39 | && typeMirrors.size() > 0) {
40 | for (TypeMirror mirror: typeMirrors) {
41 | events.add(mirror.toString());
42 | }
43 | }
44 | }
45 |
46 | if (events.size() == 0) {
47 | return null;
48 | }
49 |
50 | return new EventHandlerHolder(element, events);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/java/ru/noties/handle/benchmark/MainActivity.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.benchmark;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.view.Menu;
6 | import android.view.MenuItem;
7 |
8 | import java.util.concurrent.Executor;
9 | import java.util.concurrent.Executors;
10 |
11 | import ru.noties.debug.Debug;
12 | import ru.noties.debug.out.AndroidLogDebugOutput;
13 | import ru.noties.handle.benchmark.base.BenchmarkParams;
14 | import ru.noties.handle.benchmark.base.BenchmarkRunnable;
15 | import ru.noties.handle.benchmark.base.IEventBus;
16 | import ru.noties.handle.benchmark.base.subjects.GreenRobotEventBus;
17 | import ru.noties.handle.benchmark.base.subjects.HandleEventBus;
18 |
19 | public class MainActivity extends AppCompatActivity {
20 |
21 | @Override
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | setContentView(R.layout.activity_main);
25 |
26 | Debug.init(new AndroidLogDebugOutput(true));
27 |
28 | final IEventBus[] buses = new IEventBus[] {
29 | new HandleEventBus(),
30 | new GreenRobotEventBus(),
31 | };
32 |
33 | final BenchmarkParams[] params = new BenchmarkParams[] {
34 | new BenchmarkParams(1, 10),
35 | new BenchmarkParams(10, 1),
36 | new BenchmarkParams(10, 10),
37 | new BenchmarkParams(10, 100),
38 | new BenchmarkParams(100, 1),
39 | new BenchmarkParams(100, 1000),
40 | new BenchmarkParams(1000, 1),
41 | // new BenchmarkParams(1000, 10000)
42 | };
43 |
44 | final Executor executor = Executors.newFixedThreadPool(1);
45 |
46 | for (IEventBus bus: buses) {
47 | for (BenchmarkParams p: params) {
48 | executor.execute(new BenchmarkRunnable(p, bus));
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/java/ru/noties/handle/benchmark/base/BenchmarkRunnable.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.benchmark.base;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * Created by Dimitry Ivanov on 02.09.2015.
8 | */
9 | public class BenchmarkRunnable extends AbsBenchmarkRunnable {
10 |
11 | private final BenchmarkParams mBenchmarkParams;
12 | private final IEventBus mEventBus;
13 |
14 | public BenchmarkRunnable(BenchmarkParams params, IEventBus bus) {
15 | this.mBenchmarkParams = params;
16 | this.mEventBus = bus;
17 | }
18 |
19 | @Override
20 | public void run() {
21 |
22 | final IEventBus bus = mEventBus;
23 |
24 | final int receivers = mBenchmarkParams.subscribers;
25 | final int events = mBenchmarkParams.events;
26 |
27 | final List eventReceivers = new ArrayList<>();
28 |
29 | final EventReceiver.OnComplete onComplete = new EventReceiver.OnComplete() {
30 |
31 | int mCompleted = 0;
32 |
33 | @Override
34 | public void apply() {
35 | if (++mCompleted == receivers) {
36 | end("%s, Received %d events in %d receivers", bus.getName(), events, receivers);
37 | printResults();
38 | }
39 | }
40 | };
41 |
42 | start();
43 | for (int i = 0; i < receivers; i++) {
44 | eventReceivers.add(bus.getEventReceiver(events, onComplete));
45 | }
46 | end("%s, Generated %d receivers", bus.getName(), receivers);
47 |
48 | start();
49 | for (int i = 0; i < receivers; i++) {
50 | bus.register(eventReceivers.get(i));
51 | }
52 | end("%s, Registered %d receivers", bus.getName(), receivers);
53 |
54 | start();
55 | Object o;
56 | for (int i = 0; i < events; i++) {
57 | o = bus.newEvent();
58 | bus.post(o);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/java/ru/noties/handle/benchmark/base/subjects/GreenRobotEventBus.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.benchmark.base.subjects;
2 |
3 | import de.greenrobot.event.EventBus;
4 | import ru.noties.handle.benchmark.base.EventReceiver;
5 | import ru.noties.handle.benchmark.base.IEventBus;
6 |
7 | /**
8 | * Created by Dimitry Ivanov on 02.09.2015.
9 | */
10 | public class GreenRobotEventBus implements IEventBus {
11 |
12 | @Override
13 | public String getName() {
14 | return "GreenRobot";
15 | }
16 |
17 | @Override
18 | public void init() {
19 |
20 | }
21 |
22 | @Override
23 | public void register(Object object) {
24 | EventBus.getDefault().register(object);
25 | }
26 |
27 | @Override
28 | public void unregister(Object object) {
29 | EventBus.getDefault().unregister(object);
30 | }
31 |
32 | @Override
33 | public void post(Object object) {
34 | EventBus.getDefault().post(object);
35 | }
36 |
37 | @Override
38 | public Object newEvent() {
39 | return new GreenRobotEvent();
40 | }
41 |
42 | @Override
43 | public EventReceiver getEventReceiver(int expected, EventReceiver.OnComplete onComplete) {
44 | return new GreenRobotEventReceiver(expected, onComplete);
45 | }
46 |
47 | private static class GreenRobotEvent {
48 |
49 | }
50 |
51 | private static class GreenRobotEventReceiver implements EventReceiver {
52 |
53 | private final int mExpected;
54 | private final EventReceiver.OnComplete mOnComplete;
55 |
56 | private int mReceived;
57 |
58 | GreenRobotEventReceiver(int expected, EventReceiver.OnComplete onComplete) {
59 | this.mExpected = expected;
60 | this.mOnComplete = onComplete;
61 | }
62 |
63 | public void onEventMainThread(GreenRobotEvent o) {
64 | if (++mReceived == mExpected) {
65 | mOnComplete.apply();
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/handle-benchmark/src/main/java/ru/noties/handle/benchmark/base/subjects/HandleEventBus.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.benchmark.base.subjects;
2 |
3 | import ru.noties.handle.Handle;
4 | import ru.noties.handle.IEventHandler;
5 | import ru.noties.handle.benchmark.base.EventReceiver;
6 | import ru.noties.handle.benchmark.base.IEventBus;
7 |
8 | /**
9 | * Created by Dimitry Ivanov on 02.09.2015.
10 | */
11 | public class HandleEventBus implements IEventBus {
12 |
13 | @Override
14 | public String getName() {
15 | return "Handle";
16 | }
17 |
18 | @Override
19 | public void init() {
20 |
21 | }
22 |
23 | @Override
24 | public void register(Object object) {
25 | Handle.register((IEventHandler) object);
26 | }
27 |
28 | @Override
29 | public void unregister(Object object) {
30 | Handle.unregister((IEventHandler) object);
31 | }
32 |
33 | @Override
34 | public void post(Object object) {
35 | Handle.post(object);
36 | }
37 |
38 | @Override
39 | public Object newEvent() {
40 | return new HandleEvent();
41 | }
42 |
43 | @Override
44 | public EventReceiver getEventReceiver(int expected, EventReceiver.OnComplete onComplete) {
45 | return new HandleEventReceiver(expected, onComplete);
46 | }
47 |
48 | private static class HandleEventReceiver implements EventReceiver, IEventHandler {
49 |
50 | private final int mExpected;
51 | private final OnComplete mOnComplete;
52 |
53 | private int mReceived;
54 |
55 | HandleEventReceiver(int expected, OnComplete onComplete) {
56 | this.mExpected = expected;
57 | this.mOnComplete = onComplete;
58 | }
59 |
60 | @Override
61 | public void onEvent(Object o) {
62 | if (++mReceived == mExpected) {
63 | mOnComplete.apply();
64 | }
65 | }
66 |
67 | @Override
68 | public boolean isEventRegistered(Class> aClass) {
69 | return aClass == HandleEvent.class;
70 | }
71 | }
72 |
73 | private static class HandleEvent {
74 |
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/sample/src/main/java/ru/noties/handle/sample/NotParcelableObject.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.sample;
2 |
3 | /**
4 | * Created by Dimitry Ivanov on 21.07.2015.
5 | */
6 | public class NotParcelableObject {
7 |
8 | private String s;
9 | private int i;
10 | private long l;
11 | private NotParcelableObject o;
12 |
13 | public NotParcelableObject getO() {
14 | return o;
15 | }
16 |
17 | public NotParcelableObject setO(NotParcelableObject o) {
18 | this.o = o;
19 | return this;
20 | }
21 |
22 | public String getS() {
23 | return s;
24 | }
25 |
26 | public NotParcelableObject setS(String s) {
27 | this.s = s;
28 | return this;
29 | }
30 |
31 | public int getI() {
32 | return i;
33 | }
34 |
35 | public NotParcelableObject setI(int i) {
36 | this.i = i;
37 | return this;
38 | }
39 |
40 | public long getL() {
41 | return l;
42 | }
43 |
44 | public NotParcelableObject setL(long l) {
45 | this.l = l;
46 | return this;
47 | }
48 |
49 | @Override
50 | public boolean equals(Object o1) {
51 | if (this == o1) return true;
52 | if (o1 == null || getClass() != o1.getClass()) return false;
53 |
54 | NotParcelableObject object = (NotParcelableObject) o1;
55 |
56 | if (i != object.i) return false;
57 | if (l != object.l) return false;
58 | if (s != null ? !s.equals(object.s) : object.s != null) return false;
59 | return !(o != null ? !o.equals(object.o) : object.o != null);
60 |
61 | }
62 |
63 | @Override
64 | public int hashCode() {
65 | int result = s != null ? s.hashCode() : 0;
66 | result = 31 * result + i;
67 | result = 31 * result + (int) (l ^ (l >>> 32));
68 | result = 31 * result + (o != null ? o.hashCode() : 0);
69 | return result;
70 | }
71 |
72 | @Override
73 | public String toString() {
74 | return "NotParcelableObject{" +
75 | "s='" + s + '\'' +
76 | ", i=" + i +
77 | ", l=" + l +
78 | ", o=" + o +
79 | '}';
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/gradle_maven_jar_publish.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven'
2 | apply plugin: 'signing'
3 |
4 | def isReleaseBuild() {
5 | return VERSION_NAME.contains("SNAPSHOT") == false
6 | }
7 |
8 | def getReleaseRepositoryUrl() {
9 | return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
10 | : "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
11 | }
12 |
13 | def getSnapshotRepositoryUrl() {
14 | return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
15 | : "https://oss.sonatype.org/content/repositories/snapshots/"
16 | }
17 |
18 | def getRepositoryUsername() {
19 | return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
20 | }
21 |
22 | def getRepositoryPassword() {
23 | return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
24 | }
25 |
26 | afterEvaluate { project ->
27 | uploadArchives {
28 | repositories {
29 | mavenDeployer {
30 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
31 |
32 | pom.groupId = GROUP
33 | pom.artifactId = POM_ARTIFACT_ID
34 | pom.version = VERSION_NAME
35 |
36 | repository(url: getReleaseRepositoryUrl()) {
37 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
38 | }
39 | snapshotRepository(url: getSnapshotRepositoryUrl()) {
40 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
41 | }
42 |
43 | pom.project {
44 | name POM_NAME
45 | packaging POM_PACKAGING
46 | description POM_DESCRIPTION
47 | url POM_URL
48 |
49 | scm {
50 | url POM_SCM_URL
51 | connection POM_SCM_CONNECTION
52 | developerConnection POM_SCM_DEV_CONNECTION
53 | }
54 |
55 | licenses {
56 | license {
57 | name POM_LICENCE_NAME
58 | url POM_LICENCE_URL
59 | distribution POM_LICENCE_DIST
60 | }
61 | }
62 |
63 | developers {
64 | developer {
65 | id POM_DEVELOPER_ID
66 | name POM_DEVELOPER_NAME
67 | }
68 | }
69 | }
70 | }
71 | }
72 | }
73 |
74 | signing {
75 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
76 | sign configurations.archives
77 | }
78 |
79 | task javadocs(type: Javadoc) {
80 | source = sourceSets.main.java.srcDirs
81 | classpath += project.files()
82 | }
83 |
84 | task javadocJar(type: Jar, dependsOn: javadocs) {
85 | classifier = 'javadoc'
86 | from javadoc.destinationDir
87 | }
88 |
89 | task sourcesJar(type: Jar, dependsOn: classes) {
90 | classifier = 'sources'
91 | from sourceSets.main.allSource
92 | }
93 |
94 | artifacts {
95 | archives sourcesJar
96 | archives javadocJar
97 | }
98 | }
--------------------------------------------------------------------------------
/handle-processor/src/main/java/ru/noties/handle/processor/HandleProcessor.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.processor;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collections;
5 | import java.util.List;
6 | import java.util.Set;
7 |
8 | import javax.annotation.processing.AbstractProcessor;
9 | import javax.annotation.processing.Filer;
10 | import javax.annotation.processing.Messager;
11 | import javax.annotation.processing.ProcessingEnvironment;
12 | import javax.annotation.processing.RoundEnvironment;
13 | import javax.lang.model.SourceVersion;
14 | import javax.lang.model.element.Element;
15 | import javax.lang.model.element.TypeElement;
16 | import javax.lang.model.util.Elements;
17 | import javax.lang.model.util.Types;
18 | import javax.tools.Diagnostic;
19 |
20 | import ru.noties.handle.processor.parser.EventHandlerHolder;
21 | import ru.noties.handle.processor.parser.EventHandlerParser;
22 | import ru.noties.handle.processor.writer.EventHandlerWriter;
23 |
24 | public class HandleProcessor extends AbstractProcessor implements Logger {
25 |
26 | private Types mTypes;
27 | private Elements mElements;
28 | private Filer mFiler;
29 | private Messager mMessager;
30 |
31 | @Override
32 | public synchronized void init(ProcessingEnvironment env) {
33 | mTypes = env.getTypeUtils();
34 | mElements = env.getElementUtils();
35 | mFiler = env.getFiler();
36 | mMessager = env.getMessager();
37 | }
38 |
39 | @Override
40 | public SourceVersion getSupportedSourceVersion() {
41 | return SourceVersion.latest();
42 | }
43 |
44 | @Override
45 | public Set getSupportedAnnotationTypes() {
46 | return Collections.singleton(ru.noties.handle.annotations.EventHandler.class.getCanonicalName());
47 | }
48 |
49 | @Override
50 | public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
51 | try {
52 | for (TypeElement typeElement: annotations) {
53 | processInner(roundEnv.getElementsAnnotatedWith(typeElement));
54 | }
55 | return true;
56 | } catch (Throwable t) {
57 | log(Diagnostic.Kind.ERROR, "Error while code generation, t: %s", t);
58 | }
59 | return false;
60 | }
61 |
62 | private void processInner(Set extends Element> elements) throws Throwable {
63 | final EventHandlerParser parser = new EventHandlerParser(this);
64 | final List holders = new ArrayList<>();
65 | EventHandlerHolder holder;
66 | for (Element element: elements) {
67 | holder = parser.parse((TypeElement) element);
68 | if (holder != null) {
69 | holders.add(holder);
70 | }
71 | }
72 | if (holders.size() > 0) {
73 | final EventHandlerWriter writer = new EventHandlerWriter(this, mElements, mFiler);
74 | for (EventHandlerHolder h: holders) {
75 | writer.write(h);
76 | }
77 | }
78 | }
79 |
80 | @Override
81 | public void log(Diagnostic.Kind level, String message, Object... args) {
82 | if (args == null
83 | || args.length == 0) {
84 | mMessager.printMessage(level, message);
85 | return;
86 | }
87 | mMessager.printMessage(level, String.format(message, args));
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/sample/src/main/java/ru/noties/handle/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.sample;
2 |
3 | import android.os.Bundle;
4 | import android.os.SystemClock;
5 |
6 | import ru.noties.debug.Debug;
7 | import ru.noties.handle.Handle;
8 | import ru.noties.handle.IEventHandler;
9 | import ru.noties.handle.annotations.EventHandler;
10 |
11 | /**
12 | * Created by Dimitry Ivanov on 21.07.2015.
13 | */
14 |
15 | @EventHandler({NotParcelableObject.class, String.class, StickyEvent.class, StickyThatIsNotCancelledEvent.class})
16 | public class MainActivity extends BaseActivity {
17 |
18 | private final IEventHandler mHandler = new MainActivityEventHandler() {
19 |
20 | @Override
21 | public void onEvent(NotParcelableObject event) {
22 | Debug.i("not parcelable: %s", event);
23 | throw new NullPointerException();
24 | }
25 |
26 | @Override
27 | public void onEvent(String event) {
28 | Debug.i("string: %s", event);
29 | }
30 |
31 | @Override
32 | public void onEvent(StickyEvent event) {
33 | Debug.i("sticky, this: %s, event: %s", MainActivity.this, event.getText());
34 | Handle.cancelSticky(event);
35 | }
36 |
37 | @Override
38 | public void onEvent(StickyThatIsNotCancelledEvent event) {
39 | Debug.i("received sticky that is not cancelled event: %s", event);
40 | }
41 | };
42 |
43 | @Override
44 | public void onCreate(Bundle sis) {
45 | super.onCreate(sis);
46 | }
47 |
48 | @Override
49 | public void onStart() {
50 | super.onStart();
51 |
52 | Handle.register(mHandler);
53 |
54 | final NotParcelableObject inner = new NotParcelableObject()
55 | .setI(1)
56 | .setL(-1L)
57 | .setS("inner");
58 |
59 | final NotParcelableObject object = new NotParcelableObject()
60 | .setI(12)
61 | .setL(System.currentTimeMillis())
62 | .setS("hello handler!")
63 | .setO(inner);
64 |
65 | Handle.post(object);
66 |
67 | // for (int i = 0; i < 10; i++) {
68 | // final int j = i;
69 | // new Thread(new Runnable() {
70 | // @Override
71 | // public void run() {
72 | // try {
73 | // Thread.sleep(j * 1000L);
74 | // } catch (InterruptedException e) {
75 | // e.printStackTrace();
76 | // }
77 | // Handle.post(object);
78 | // Handle.post(String.format("thread: %s", Thread.currentThread()));
79 | // Handle.post(new Object());
80 | // }
81 | // }).start();
82 | // }
83 | //
84 | Handle.postDelayed("Delay", 1000L);
85 | Handle.postAtTime("AtTime", SystemClock.uptimeMillis() + 2000L);
86 |
87 | // Handle.postSticky(new StickyEvent(String.format("this: %s", this)));
88 | }
89 |
90 | @Override
91 | public void onStop() {
92 | super.onStop();
93 |
94 | Handle.unregister(mHandler);
95 |
96 | Handle.postSticky(new StickyEvent(String.format("%s", this)));
97 | Handle.postSticky(new StickyThatIsNotCancelledEvent());
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/handle-library/src/main/java/ru/noties/handle/HandleHandler.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 | import android.os.Message;
6 |
7 | import java.util.List;
8 |
9 | import ru.noties.handle.events.NoEventHandlerEvent;
10 | import ru.noties.handle.events.OnDispatchExceptionEvent;
11 | import ru.noties.handle.events.StickyEventNotUsedEvent;
12 |
13 | /**
14 | * Created by Dimitry Ivanov on 21.07.2015.
15 | */
16 | class HandleHandler extends Handler {
17 |
18 | enum HandleMessageType {
19 |
20 | NORMAL(1), DELAYED(2), AT_TIME(3), STICKY(4), STICKY_VALID(5), SPECIAL(6);
21 |
22 | final int type;
23 |
24 | HandleMessageType(int type) {
25 | this.type = type;
26 | }
27 |
28 | static HandleMessageType forValue(int v) {
29 | final HandleMessageType[] types = HandleMessageType.values();
30 | for (int i = types.length; --i >= 0; ) {
31 | if (types[i].type == v) {
32 | return types[i];
33 | }
34 | }
35 | return null;
36 | }
37 | }
38 |
39 | void post(Object what) {
40 | final Message msg = obtain(HandleMessageType.NORMAL, what);
41 | sendMessage(msg);
42 | }
43 |
44 | private void postSpecial(Object what) {
45 | final Message msg = obtain(HandleMessageType.SPECIAL, what);
46 | sendMessage(msg);
47 | }
48 |
49 | void postDelayed(Object what, long delayMillis) {
50 | final Message msg = obtain(HandleMessageType.DELAYED, what);
51 | sendMessageDelayed(msg, delayMillis);
52 | }
53 |
54 | void postAtTime(Object what, long uptimeMillis) {
55 | final Message msg = obtain(HandleMessageType.AT_TIME, what);
56 | sendMessageAtTime(msg, uptimeMillis);
57 | }
58 |
59 | void postSticky(Object what) {
60 | final Message msg = obtain(HandleMessageType.STICKY, what);
61 | sendMessage(msg);
62 | }
63 |
64 | void postStickyValid(Object what, long delay) {
65 | final Message msg = obtain(HandleMessageType.STICKY_VALID, what);
66 | sendMessageDelayed(msg, delay);
67 | }
68 |
69 | void cancel(Object what) {
70 | final HandleMessageType[] types = HandleMessageType.values();
71 | for (int i = types.length - 1; --i >= 0; ) { // ignore stickies
72 | removeMessages(types[i].type, what);
73 | }
74 | }
75 |
76 | private Message obtain(HandleMessageType type, Object what) {
77 | return obtainMessage(type.type, what);
78 | }
79 |
80 | public HandleHandler(Looper looper) {
81 | super(looper);
82 | }
83 |
84 | @Override
85 | public void handleMessage(Message msg) {
86 | final HandleMessageType type = HandleMessageType.forValue(msg.what);
87 | if (type == null
88 | || msg.obj == null) {
89 | return;
90 | }
91 |
92 | final Object obj;
93 | switch (type) {
94 | case STICKY_VALID:
95 | obj = new StickyEventNotUsedEvent(msg.obj);
96 | break;
97 | default:
98 | obj = msg.obj;
99 | break;
100 | }
101 |
102 | final List handlers = Handle.getEventHandlers(obj.getClass());
103 | if (handlers != null
104 | && handlers.size() > 0) {
105 | for (IEventHandler eventHandler: handlers) {
106 | try {
107 | eventHandler.onEvent(obj);
108 | } catch (Throwable t) {
109 | postSpecial(new OnDispatchExceptionEvent(eventHandler.getClass(), obj, t));
110 | }
111 | }
112 | } else {
113 | // if there are no event handlers for NoEventHandlerEvent don't send it
114 | if (type != HandleMessageType.SPECIAL) {
115 | postSpecial(new NoEventHandlerEvent(obj));
116 | }
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/handle-processor/src/main/java/ru/noties/handle/processor/writer/EventHandlerWriter.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.processor.writer;
2 |
3 | import java.io.IOException;
4 | import java.io.Writer;
5 | import java.util.List;
6 |
7 | import javax.annotation.processing.Filer;
8 | import javax.lang.model.element.Element;
9 | import javax.lang.model.element.TypeElement;
10 | import javax.lang.model.util.Elements;
11 | import javax.tools.Diagnostic;
12 | import javax.tools.JavaFileObject;
13 |
14 | import ru.noties.handle.processor.Logger;
15 | import ru.noties.handle.processor.parser.EventHandlerHolder;
16 |
17 | /**
18 | * Created by Dimitry Ivanov on 21.07.2015.
19 | */
20 | public class EventHandlerWriter {
21 |
22 | private static final String OBJECT = "java.lang.Object";
23 |
24 | private final Logger mLogger;
25 | private final Elements mElements;
26 | private final Filer mFiler;
27 |
28 | public EventHandlerWriter(Logger logger, Elements elements, Filer filer) {
29 | this.mLogger = logger;
30 | this.mElements = elements;
31 | this.mFiler = filer;
32 | }
33 |
34 | public void write(EventHandlerHolder holder) {
35 |
36 | final TypeElement element = holder.element;
37 |
38 | final String holderPackage = mElements.getPackageOf(element).toString();
39 | final String holderClassName = createClassName(element);
40 |
41 | final Indent indent = new Indent();
42 |
43 | final StringBuilder builder = new StringBuilder();
44 | builder.append("package ")
45 | .append(holderPackage)
46 | .append(";\n");
47 | builder.append("public abstract class ")
48 | .append(holderClassName)
49 | .append(" implements ru.noties.handle.IEventHandler")
50 | .append(" {\n");
51 |
52 | indent.increment();
53 |
54 | final List events = holder.eventClasses;
55 | if (events.contains(OBJECT)) {
56 | events.remove(OBJECT);
57 | }
58 |
59 | if (events.size() == 0) {
60 | return;
61 | }
62 |
63 | for (String event: events) {
64 | builder.append(indent);
65 | builder.append("public abstract void onEvent(")
66 | .append(event)
67 | .append(" event);");
68 | builder.append('\n');
69 | }
70 |
71 | builder
72 | .append(indent)
73 | .append("public final void onEvent(Object o) {\n");
74 | indent.increment();
75 | builder
76 | .append(indent)
77 | .append("final Class> c = o.getClass();\n");
78 |
79 | boolean isFirst = true;
80 | for (String event: events) {
81 | builder.append(indent);
82 | if (!isFirst) {
83 | builder.append("else ");
84 | } else {
85 | isFirst = false;
86 | }
87 | builder
88 | .append("if (c == ")
89 | .append(event)
90 | .append(".class) this.onEvent((")
91 | .append(event)
92 | .append(") o);\n");
93 | }
94 | builder.append(indent.decrement())
95 | .append("}\n");
96 |
97 | builder.append(indent)
98 | .append("public final boolean isEventRegistered(Class> c) {\n")
99 | .append(indent.increment())
100 | .append("return ");
101 |
102 | isFirst = true;
103 | for (String event: events) {
104 | if (!isFirst) {
105 | builder.append(" || ");
106 | } else {
107 | isFirst = false;
108 | }
109 | builder.append("c == ")
110 | .append(event)
111 | .append(".class");
112 | }
113 | builder.append(";\n")
114 | .append(indent.decrement())
115 | .append("}\n");
116 |
117 | builder.append("}");
118 |
119 | Writer writer = null;
120 | try {
121 | final JavaFileObject javaFileObject = mFiler.createSourceFile(holderPackage + "." + holderClassName);
122 | writer = javaFileObject.openWriter();
123 | writer.write(builder.toString());
124 | } catch (IOException e) {
125 | mLogger.log(Diagnostic.Kind.ERROR, "Error writing java source file, e: %s", e);
126 | } finally {
127 | if (writer != null) {
128 | try {
129 | writer.flush();
130 | writer.close();
131 | } catch (IOException e) {}
132 | }
133 | }
134 | }
135 |
136 | private static String createClassName(Element e) {
137 | return e.getSimpleName().toString() + "EventHandler";
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://android-arsenal.com/details/1/2437)
2 |
3 | # Handle
4 | Handler-based Eventbus for Android
5 |
6 |
7 | ### Features
8 | * No Reflection during runtime
9 | * Reusable Event-handlers
10 | * Sticky events with controllable lifetime
11 | * android.os.Handler underneath
12 | * Extremely fast and lightweight
13 | * Ability to generate event handlers with `apt`
14 |
15 | ### Basic usage
16 | [](http://search.maven.org/#search|ga|1|g%3A%22ru.noties.handle%22%20AND%20a%3A%22core%22)
17 | ```groovy
18 | compile 'ru.noties.handle:core:x.x.x'
19 | ```
20 | #### Introduction
21 | The Handle library revolves around event handlers. To start using Handle one must create an implementation of the `ru.noties.handle.IEventHandler`
22 | ```java
23 | public interface IEventHandler {
24 | void onEvent(Object event);
25 | boolean isEventRegistered(Class> cl);
26 | }
27 | ```
28 | Then, as usual
29 | ```java
30 | Handle.register(IEventHandler);
31 | Handle.unregister(IEventHandler);
32 | ```
33 |
34 | #### Simple Posting
35 | As long as Handle hides `android.os.Handler` posting could be done with these methods:
36 | ```java
37 | Handle.post(Object); // simple
38 | Handle.postDelayed(Object, long); // with delay
39 | Handle.postAtTime(Object, SystemUptimeMillis + delay); // posting at specific time in the future
40 | ```
41 | Also, there is a possibility to cancel every enqueued simple event:
42 | ```java
43 | Handle.cancel(Object)
44 | ```
45 |
46 | #### Sticky posting
47 | Handle gives an ability to post sticky events and control its' lifetime
48 | ```java
49 | Handle.postSticky(Object); // simple with default lifetime (currently 30 seconds)
50 | Handle.postSticky(Object, long validMillis); // with custom lifetime
51 | ```
52 | Every posted sticky event is intended to be cancelled at some point, that's why after sticky event is recieved one should cancel its delivery
53 | ```java
54 | Handle.cancelSticky(Object);
55 | ```
56 | If sticky event is not cancelled after it's specified duration of lifetime `ru.noties.handle.events.StickyEventNotUsedEvent` is fired, which gives an ability to cancel it.
57 |
58 | If you wish to cancel all pending events (including sticky) call:
59 | ```java
60 | Handle.cancelAll();
61 | ```
62 |
63 | #### Special events
64 | * `ru.noties.handle.events.StickyEventNotUsedEvent` is fired when StickyEvent is not cancelled after its lifetime
65 | * `ru.noties.handle.events.OnDispatchExceptionEvent` is fired when an Exception was thrown during event delivery
66 | * `ru.noties.handle.events.NoEventHandlerEvent` is fired when posted Event has no IEventHandler which can receive it
67 |
68 | ### Code generation (apt)
69 | Handle also comes with `processor` and `annotations` modules
70 |
71 | [](http://search.maven.org/#search|ga|1|g%3A%22ru.noties.handle%22%20AND%20a%3A%22processor%22)
72 | [](http://search.maven.org/#search|ga|1|g%3A%22ru.noties.handle%22%20AND%20a%3A%22annotations%22)
73 | ```groovy
74 | apt 'ru.noties.handle:processor:x.x.x'
75 | compile 'ru.noties.handle:annotations:x.x.x'
76 | ```
77 | Annotate the class, which would receive events with `@ru.noties.handle.annotations.EventHandler`, for example (from sample application)
78 | ```java
79 | @EventHandler({ OnDispatchExceptionEvent.class, NoEventHandlerEvent.class, StickyEventNotUsedEvent.class})
80 | public class BaseActivity extends Activity { }
81 | ```
82 | After `build` there will be a generated IEventHandler in the package of annotated class with the name `*EventHandler` (continued from sample application):
83 | ```java
84 | private final IEventHandler mHandler = new BaseActivityEventHandler() {
85 | @Override
86 | public void onEvent(OnDispatchExceptionEvent event) {
87 | Debug.e(event.getThrowable(), "Handler: %s, event: %s", event.getEventHandler(), event.getEvent());
88 | }
89 |
90 | @Override
91 | public void onEvent(NoEventHandlerEvent event) {
92 | Debug.i("noEventHandler: %s", event.getEvent());
93 | }
94 |
95 | @Override
96 | public void onEvent(StickyEventNotUsedEvent event) {
97 | final Object sticky = event.getStickyEvent();
98 | Debug.i("sticky no used, removing, sticky: %s", sticky);
99 | Handle.cancelSticky(sticky);
100 | }
101 | };
102 | ```
103 |
104 | ## License
105 |
106 | ```
107 | Copyright 2015 Dimitry Ivanov (mail@dimitryivanov.ru)
108 |
109 | Licensed under the Apache License, Version 2.0 (the "License");
110 | you may not use this file except in compliance with the License.
111 | You may obtain a copy of the License at
112 |
113 | http://www.apache.org/licenses/LICENSE-2.0
114 |
115 | Unless required by applicable law or agreed to in writing, software
116 | distributed under the License is distributed on an "AS IS" BASIS,
117 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118 | See the License for the specific language governing permissions and
119 | limitations under the License.
120 | ```
--------------------------------------------------------------------------------
/handle-library-test/src/androidTest/java/ru/noties/handle/test/HandleTest.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle.test;
2 |
3 | import junit.framework.TestCase;
4 |
5 | import ru.noties.handle.Handle;
6 | import ru.noties.handle.HandleMediator;
7 | import ru.noties.handle.IEventHandler;
8 | import ru.noties.handle.events.NoEventHandlerEvent;
9 | import ru.noties.handle.events.OnDispatchExceptionEvent;
10 | import ru.noties.handle.events.StickyEventNotUsedEvent;
11 |
12 | /**
13 | * Created by Dimitry Ivanov on 03.08.2015.
14 | */
15 | public class HandleTest extends TestCase {
16 |
17 | @Override
18 | public void tearDown() throws Exception {
19 | super.tearDown();
20 | HandleMediator.clear();
21 | }
22 |
23 | public void testRegister() {
24 | final IEventHandler handler = new NoOpEventHandler();
25 | final boolean result = Handle.register(handler);
26 | assertTrue(result);
27 | assertTrue(Handle.isRegistered(handler));
28 | }
29 |
30 | public void testNotRegistered() {
31 | assertFalse(Handle.isRegistered(new NoOpEventHandler()));
32 | }
33 |
34 | public void testUnregister() {
35 | final IEventHandler handler = new NoOpEventHandler();
36 | final boolean result = Handle.register(handler);
37 | assertTrue(result);
38 | assertTrue(Handle.isRegistered(handler));
39 | final boolean unregister = Handle.unregister(handler);
40 | assertTrue(unregister);
41 | assertFalse(Handle.isRegistered(handler));
42 | }
43 |
44 | public void testEventHandler() {
45 | final IEventHandler handler = new IEventHandler() {
46 | @Override
47 | public void onEvent(Object event) {
48 |
49 | }
50 |
51 | @Override
52 | public boolean isEventRegistered(Class> cl) {
53 | return cl == String.class;
54 | }
55 | };
56 | assertTrue(handler.isEventRegistered(String.class));
57 | assertFalse(handler.isEventRegistered(Integer.class));
58 | }
59 |
60 | public void testDeliverySingleRecipient() {
61 | final int count = 10000;
62 | final CountEventHandler handler = new CountEventHandler();
63 | Handle.register(handler);
64 | for (int i = count; --i > -1; ) {
65 | Handle.post("");
66 | }
67 |
68 | sleep(5000L);
69 |
70 | assertEquals(count, handler.received);
71 | }
72 |
73 | public void testDeliveryMultipleRecipients() {
74 | final int handlersCount = 100;
75 | final CountEventHandler[] handlers = new CountEventHandler[handlersCount];
76 | for (int i = handlersCount; --i > -1; ) {
77 | handlers[i] = new CountEventHandler();
78 | Handle.register(handlers[i]);
79 | }
80 |
81 | final int count = 1000;
82 | for (int i = count; --i > -1; ) {
83 | Handle.post("");
84 | }
85 |
86 | sleep(5000L);
87 |
88 | for (CountEventHandler handler: handlers) {
89 | assertEquals(count, handler.received);
90 | }
91 | }
92 |
93 | public void testStickies() {
94 | final CountEventHandler handler = new CountEventHandler();
95 | Handle.register(handler);
96 | assertEquals(0, handler.received);
97 |
98 | final String s = "";
99 |
100 | Handle.postSticky(s);
101 |
102 | sleep(1000L);
103 |
104 | assertEquals(1, handler.received);
105 |
106 | final CountEventHandler otherHandler = new CountEventHandler();
107 | Handle.register(otherHandler);
108 | assertEquals(1, otherHandler.received);
109 | }
110 |
111 | public void testCancelSticky() {
112 | final String s = "";
113 | Handle.postSticky(s);
114 | Handle.cancelSticky(s);
115 | final CountEventHandler handler = new CountEventHandler();
116 | Handle.register(handler);
117 | assertEquals(0, handler.received);
118 | }
119 |
120 | public void testNotUsedSticky() {
121 | final ClassEventHandler handler = new ClassEventHandler(StickyEventNotUsedEvent.class);
122 | Handle.register(handler);
123 | final long valid = 1000L;
124 | Handle.postSticky("sticky", valid);
125 |
126 | sleep(valid * 2);
127 |
128 | assertEquals(1, handler.received);
129 | }
130 |
131 | private static void sleep(long millis) {
132 | try {
133 | Thread.sleep(millis);
134 | } catch (InterruptedException e) {
135 | e.printStackTrace();
136 | }
137 | }
138 |
139 | public void testNoHandler() {
140 | final ClassEventHandler handler = new ClassEventHandler(NoEventHandlerEvent.class);
141 | Handle.register(handler);
142 | Handle.post("");
143 | sleep(2000L);
144 | assertEquals(1, handler.received);
145 | }
146 |
147 | public void testException() {
148 | final ClassEventHandler handler = new ClassEventHandler(OnDispatchExceptionEvent.class);
149 | final IEventHandler ex = new IEventHandler() {
150 | @Override
151 | public void onEvent(Object event) {
152 | throw new NullPointerException();
153 | }
154 |
155 | @Override
156 | public boolean isEventRegistered(Class> cl) {
157 | return cl == String.class;
158 | }
159 | };
160 | Handle.register(handler);
161 | Handle.register(ex);
162 | Handle.post("");
163 |
164 | sleep(2000L);
165 | assertEquals(1, handler.received);
166 | }
167 |
168 | private static class NoOpEventHandler implements IEventHandler {
169 |
170 | @Override
171 | public void onEvent(Object event) {
172 |
173 | }
174 |
175 | @Override
176 | public boolean isEventRegistered(Class> cl) {
177 | return false;
178 | }
179 | }
180 |
181 | private static class CountEventHandler implements IEventHandler {
182 |
183 | int received;
184 |
185 | @Override
186 | public void onEvent(Object event) {
187 | received++;
188 | }
189 |
190 | @Override
191 | public boolean isEventRegistered(Class> cl) {
192 | return true;
193 | }
194 | }
195 |
196 | private static class ClassEventHandler implements IEventHandler {
197 |
198 | final Class> cl;
199 | int received;
200 |
201 | private ClassEventHandler(Class> cl) {
202 | this.cl = cl;
203 | }
204 |
205 | @Override
206 | public void onEvent(Object event) {
207 | received++;
208 | }
209 |
210 | @Override
211 | public boolean isEventRegistered(Class> cl) {
212 | return this.cl == cl;
213 | }
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/handle-library/src/main/java/ru/noties/handle/Handle.java:
--------------------------------------------------------------------------------
1 | package ru.noties.handle;
2 |
3 | import android.app.Activity;
4 | import android.app.Fragment;
5 | import android.os.Looper;
6 | import android.os.SystemClock;
7 |
8 | import java.util.ArrayList;
9 | import java.util.HashSet;
10 | import java.util.List;
11 | import java.util.Set;
12 |
13 | import ru.noties.handle.events.StickyEventNotUsedEvent;
14 |
15 | /**
16 | * Main class for this library.
17 | *
18 | * The idea behind Handle is simple - create an event bus implementation specific for the Android platform.
19 | * This library relies on {@link android.os.Handler} to queue and deliver events and {@link IEventHandler}
20 | * to process these events.
21 | *
22 | * With the help of this library it becomes easy to reuse event handlers
23 | *
24 | * This library does not use reflection.
25 | *
26 | * Note that all events are delivered in Main thread
27 | *
28 | * @see #register(IEventHandler)
29 | * @see #unregister(IEventHandler)
30 | * @see #isRegistered(IEventHandler)
31 | *
32 | * @see #post(Object)
33 | * @see #postDelayed(Object, long)
34 | * @see #postAtTime(Object, long)
35 | * @see #cancel(Object)
36 | *
37 | * @see #postSticky(Object)
38 | * @see #cancelSticky(Object)
39 | *
40 | * @see #cancelAll()
41 | *
42 | * Created by Dimitry Ivanov on 21.07.2015.
43 | */
44 | public class Handle {
45 |
46 | private static volatile Handle sInstance = null;
47 |
48 | public static Handle getInstance() {
49 | Handle local = sInstance;
50 | if (local == null) {
51 | synchronized (Handle.class) {
52 | local = sInstance;
53 | if (local == null) {
54 | local = sInstance = new Handle();
55 | }
56 | }
57 | }
58 | return local;
59 | }
60 |
61 | public static final long DEF_STICKY_VALID_MILLIS = 1000L * 30;
62 |
63 | private final HandleHandler mHandler;
64 | private final Set mListeners;
65 | private final Set