Skip to content

Commit

Permalink
创建LiveEventBus工程
Browse files Browse the repository at this point in the history
  • Loading branch information
huanghaihua committed Aug 31, 2019
1 parent fb95359 commit d4a20e5
Show file tree
Hide file tree
Showing 15 changed files with 840 additions and 29 deletions.
6 changes: 6 additions & 0 deletions app/build.gradle
Expand Up @@ -17,6 +17,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {
Expand All @@ -26,4 +30,6 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

implementation project(path: ':liveeventbus')
}
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hhh.liveeventbus" >
package="com.hhh.app" >

<application
android:allowBackup="true"
Expand Down
44 changes: 44 additions & 0 deletions app/src/main/java/com/hhh/app/MainActivity.java
@@ -0,0 +1,44 @@
package com.hhh.app;

import android.os.Bundle;
import android.widget.Toast;

import com.hhh.liveeventbus.LiveEventBus;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentActivity;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testSendEvent();
testAcceptEvent(this);
}

private void testSendEvent() {
findViewById(R.id.post).setOnClickListener(view -> LiveEventBus.getInstance()
.with(TestEvent.class).post(new TestEvent("post")));
findViewById(R.id.post_delay).setOnClickListener(view -> LiveEventBus.getInstance()
.with(TestEvent.class).postDelay(new TestEvent("postDelay"), 1000L));
findViewById(R.id.post_orderly).setOnClickListener(view -> LiveEventBus.getInstance()
.with(TestEvent.class).postOrderly(new TestEvent("postOrderly")));
}

private void testAcceptEvent(FragmentActivity activity) {
findViewById(R.id.observe).setOnClickListener(
view -> LiveEventBus.getInstance().with(TestEvent.class).observe(activity,
testEvent -> Toast.makeText(activity, testEvent.mEvent, Toast.LENGTH_SHORT).show()));
findViewById(R.id.observe_sticky).setOnClickListener(view -> LiveEventBus.getInstance()
.with(TestEvent.class).observeSticky(activity, testEvent -> Toast
.makeText(activity, "stick: " + testEvent.mEvent, Toast.LENGTH_SHORT).show()));
findViewById(R.id.observe_forever).setOnClickListener(
view -> LiveEventBus.getInstance().with(TestEvent.class).observeForever(testEvent -> Toast
.makeText(activity, "forever: " + testEvent.mEvent, Toast.LENGTH_SHORT).show()));
findViewById(R.id.observe_sticky_forever).setOnClickListener(view -> LiveEventBus.getInstance()
.with(TestEvent.class).observeStickyForever(testEvent -> Toast
.makeText(activity, "sticky_forever: " + testEvent.mEvent, Toast.LENGTH_SHORT).show()));
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/com/hhh/app/TestEvent.java
@@ -0,0 +1,12 @@
package com.hhh.app;

import androidx.annotation.NonNull;

public final class TestEvent {

public final String mEvent;

public TestEvent(@NonNull String event) {
mEvent = event;
}
}
13 changes: 0 additions & 13 deletions app/src/main/java/com/hhh/liveeventbus/MainActivity.java

This file was deleted.

66 changes: 52 additions & 14 deletions app/src/main/res/layout/activity_main.xml
@@ -1,19 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<Button
android:id="@+id/post"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="post"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/post_delay"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
android:layout_height="wrap_content"
android:text="post_delay"
app:layout_constraintTop_toBottomOf="@id/post" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/post_orderly"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="post_orderly"
app:layout_constraintTop_toBottomOf="@id/post_delay" />

<Button
android:id="@+id/observe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="observe"
app:layout_constraintTop_toBottomOf="@id/post_orderly" />

<Button
android:id="@+id/observe_sticky"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="observe_sticky"
app:layout_constraintTop_toBottomOf="@id/observe" />

<Button
android:id="@+id/observe_forever"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="observe_forever"
app:layout_constraintTop_toBottomOf="@id/observe_sticky" />

<Button
android:id="@+id/observe_sticky_forever"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="observe_sticky_forever"
app:layout_constraintTop_toBottomOf="@id/observe_forever" />
</androidx.constraintlayout.widget.ConstraintLayout>
1 change: 1 addition & 0 deletions liveeventbus/.gitignore
@@ -0,0 +1 @@
/build
39 changes: 39 additions & 0 deletions liveeventbus/build.gradle
@@ -0,0 +1,39 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion 29
buildToolsVersion "29.0.2"


defaultConfig {
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
implementation 'androidx.appcompat:appcompat:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
2 changes: 2 additions & 0 deletions liveeventbus/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hhh.liveeventbus" />
129 changes: 129 additions & 0 deletions liveeventbus/src/main/java/com/hhh/liveeventbus/LiveEvent.java
@@ -0,0 +1,129 @@
package com.hhh.liveeventbus;

import java.util.HashMap;
import java.util.Map;

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.Observer;

class LiveEvent<T> implements Observable<T> {

private static final Handler HANDLER = new Handler(Looper.getMainLooper());
private final LiveEventData<T> mLiveData = new LiveEventData<>();
private final Map<Observer, ObserverWrapper<T>> mObserverMap = new HashMap<>();

private static boolean isMainThread() {
return Looper.getMainLooper().getThread() == Thread.currentThread();
}

@Override
public void post(@Nullable T value) {
if (isMainThread()) {
postInternal(value);
} else {
HANDLER.post(() -> postInternal(value));
}
}

@Override
public void postDelay(@Nullable T value, long delay) {
HANDLER.postDelayed(() -> postInternal(value), delay);
}

@Override
public void postOrderly(@Nullable T value) {
HANDLER.post(() -> postInternal(value));
}

@Override
public void observe(@NonNull final LifecycleOwner owner, @NonNull final Observer<T> observer) {
if (isMainThread()) {
observeInternal(owner, observer);
} else {
HANDLER.post(() -> observeInternal(owner, observer));
}
}

@Override
public void observeSticky(@NonNull final LifecycleOwner owner,
@NonNull final Observer<T> observer) {
if (isMainThread()) {
observeStickyInternal(owner, observer);
} else {
HANDLER.post(() -> observeStickyInternal(owner, observer));
}
}

@Override
public void observeForever(@NonNull final Observer<T> observer) {
if (isMainThread()) {
observeForeverInternal(observer);
} else {
HANDLER.post(() -> observeForeverInternal(observer));
}
}

@Override
public void observeStickyForever(@NonNull final Observer<T> observer) {
if (isMainThread()) {
observeStickyForeverInternal(observer);
} else {
HANDLER.post(() -> observeStickyForeverInternal(observer));
}
}

@Override
public void removeObserver(@NonNull final Observer<T> observer) {
if (isMainThread()) {
removeObserverInternal(observer);
} else {
HANDLER.post(() -> removeObserverInternal(observer));
}
}

@MainThread
private void postInternal(T value) {
mLiveData.setValue(value);
}

@MainThread
private void observeInternal(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
ObserverWrapper<T> observerWrapper = new ObserverWrapper<>(observer);
observerWrapper.mPreventNextEvent = mLiveData.getVersion() > LiveEventData.START_VERSION;
mLiveData.observe(owner, observerWrapper);
}

@MainThread
private void observeStickyInternal(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
mLiveData.observe(owner, new ObserverWrapper<>(observer));
}

@MainThread
private void observeForeverInternal(@NonNull Observer<T> observer) {
ObserverWrapper<T> observerWrapper = new ObserverWrapper<>(observer);
observerWrapper.mPreventNextEvent = mLiveData.getVersion() > LiveEventData.START_VERSION;
mObserverMap.put(observer, observerWrapper);
mLiveData.observeForever(observerWrapper);
}

@MainThread
private void observeStickyForeverInternal(@NonNull Observer<T> observer) {
ObserverWrapper<T> observerWrapper = new ObserverWrapper<>(observer);
mObserverMap.put(observer, observerWrapper);
mLiveData.observeForever(observerWrapper);
}

@MainThread
private void removeObserverInternal(@NonNull Observer<T> observer) {
if (mObserverMap.containsKey(observer)) {
observer = mObserverMap.remove(observer);
}
mLiveData.removeObserver(observer);
}
}
39 changes: 39 additions & 0 deletions liveeventbus/src/main/java/com/hhh/liveeventbus/LiveEventBus.java
@@ -0,0 +1,39 @@
package com.hhh.liveeventbus;

import java.util.HashMap;
import java.util.Map;

import androidx.annotation.MainThread;
import androidx.annotation.NonNull;

public class LiveEventBus {

private static final LiveEventBus LIVE_EVENT_BUS = new LiveEventBus();

private final Map<String, LiveEvent<Object>> mEventMap = new HashMap<>();

private LiveEventBus() {}

@NonNull
public static LiveEventBus getInstance() {
return LIVE_EVENT_BUS;
}

@NonNull
@MainThread
public <T> Observable<T> with(@NonNull Class<T> type) {
return with(type.getName(), type);
}

/**
* 之所以要求在主线程,是不想加锁,只要不是高并发,在子线程也不会有问题
*/
@NonNull
@MainThread
public <T> Observable<T> with(@NonNull String key, @NonNull Class<T> type) {
if (!mEventMap.containsKey(key)) {
mEventMap.put(key, new LiveEvent<>());
}
return (Observable<T>) mEventMap.get(key);
}
}

0 comments on commit d4a20e5

Please sign in to comment.