Commit fffb7f32 by zhengnw@sobot.com

widget 1.1.3 添加livedata 事件总线

parent 7a5ea746
......@@ -13,7 +13,7 @@ ext {
PUBLISH_GROUP_ID = "com.sobot.library" //项目包名
PUBLISH_ARTIFACT_ID = 'widget' //项目名
// PUBLISH_ARTIFACT_ID = 'widget_x' //项目名
PUBLISH_VERSION = '1.1.2' //版本号
PUBLISH_VERSION = '1.1.3' //版本号
}
......
package android.arch.lifecycle;
import static android.arch.lifecycle.Lifecycle.State.CREATED;
import static android.arch.lifecycle.Lifecycle.State.DESTROYED;
import android.support.annotation.NonNull;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ExternalLiveData<T> extends MutableLiveData<T> {
public static final int START_VERSION = LiveData.START_VERSION;
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
try {
//use ExternalLifecycleBoundObserver instead of LifecycleBoundObserver
LifecycleBoundObserver wrapper = new ExternalLifecycleBoundObserver(owner, observer);
LifecycleBoundObserver existing = (LifecycleBoundObserver) callMethodPutIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
} catch (Exception e) {
e.printStackTrace();
}
}
public int getVersion() {
return super.getVersion();
}
/**
* determine when the observer is active, means the observer can receive message
* the default value is CREATED, means if the observer's state is above create,
* for example, the onCreate() of activity is called
* you can change this value to CREATED/STARTED/RESUMED
* determine on witch state, you can receive message
*
* @return Lifecycle.State
*/
protected Lifecycle.State observerActiveLevel() {
return CREATED;
}
class ExternalLifecycleBoundObserver extends LifecycleBoundObserver {
ExternalLifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
super(owner, observer);
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(observerActiveLevel());
}
}
private Object getFieldObservers() throws Exception {
Field fieldObservers = LiveData.class.getDeclaredField("mObservers");
fieldObservers.setAccessible(true);
return fieldObservers.get(this);
}
private Object callMethodPutIfAbsent(Object observer, Object wrapper) throws Exception {
Object mObservers = getFieldObservers();
Class<?> classOfSafeIterableMap = mObservers.getClass();
Method putIfAbsent = classOfSafeIterableMap.getDeclaredMethod("putIfAbsent",
Object.class, Object.class);
putIfAbsent.setAccessible(true);
return putIfAbsent.invoke(mObservers, observer, wrapper);
}
}
package com.sobot.widget.livedatabus;
import android.support.annotation.NonNull;
import com.sobot.widget.livedatabus.core.Config;
import com.sobot.widget.livedatabus.core.LiveEvent;
import com.sobot.widget.livedatabus.core.LiveEventBusCore;
import com.sobot.widget.livedatabus.core.Observable;
import com.sobot.widget.livedatabus.core.ObservableConfig;
public class SobotLiveEventBus {
/**
* get observable by key with type
*
* @param key key
* @param type type
* @param <T> T
* @return Observable
*/
public static <T> Observable<T> get(@NonNull String key, @NonNull Class<T> type) {
return LiveEventBusCore.get().with(key, type);
}
/**
* get observable by key
*
* @param key String
* @param <T> T
* @return Observable
*/
public static <T> Observable<T> get(@NonNull String key) {
return (Observable<T>) get(key, Object.class);
}
/**
* get observable from eventType
*
* @param eventType Class
* @param <T> T
* @return Observable
*/
public static <T extends LiveEvent> Observable<T> get(@NonNull Class<T> eventType) {
return get(eventType.getName(), eventType);
}
/**
* use the inner class Config to set params
* first of all, call config to get the Config instance
* then, call the method of Config to config LiveEventBus
* call this method in Application.onCreate
* @return Config
*/
public static Config config() {
return LiveEventBusCore.get().config();
}
/**
* use the inner class Config to set params
* first of all, call config to get the Config instance
* then, call the method of Config to config LiveEventBus
* call this method in Application.onCreate
* @param key String
* @return Config
*/
public static ObservableConfig config(@NonNull String key) {
return LiveEventBusCore.get().config(key);
}
}
\ No newline at end of file
package com.sobot.widget.livedatabus.core;
import android.content.Context;
import android.support.annotation.NonNull;
import com.sobot.widget.livedatabus.logger.Logger;
import com.sobot.widget.livedatabus.utils.AppUtils;
public class Config {
/**
* lifecycleObserverAlwaysActive
* set if then observer can always receive message
* true: observer can always receive message
* false: observer can only receive message when resumed
*
* @param active boolean
* @return Config
*/
public Config lifecycleObserverAlwaysActive(boolean active) {
LiveEventBusCore.get().setLifecycleObserverAlwaysActive(active);
return this;
}
/**
* @param clear boolean
* @return true: clear livedata when no observer observe it
* false: not clear livedata unless app was killed
*/
public Config autoClear(boolean clear) {
LiveEventBusCore.get().setAutoClear(clear);
return this;
}
/**
* config broadcast
* only if you called this method, you can use broadcastValue() to send broadcast message
*
* @param context Context
* @return Config
*/
public Config setContext(Context context) {
AppUtils.init(context);
LiveEventBusCore.get().registerReceiver();
return this;
}
/**
* setLogger, if not set, use DefaultLogger
*
* @param logger Logger
* @return Config
*/
public Config setLogger(@NonNull Logger logger) {
LiveEventBusCore.get().setLogger(logger);
return this;
}
/**
* set logger enable or disable, default enable
*
* @param enable boolean
* @return Config
*/
public Config enableLogger(boolean enable) {
LiveEventBusCore.get().enableLogger(enable);
return this;
}
}
package com.sobot.widget.livedatabus.core;
/**
* 调试信息控制台
*/
public final class Console {
private Console() {
}
/**
* 获取控制台信息
*
* @return 调试信息
*/
public static String getInfo() {
return LiveEventBusCore.get().console.getConsoleInfo();
}
}
package com.sobot.widget.livedatabus.core;
import java.io.Serializable;
public interface LiveEvent extends Serializable {
}
package com.sobot.widget.livedatabus.core;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.Observer;
import android.support.annotation.NonNull;
public interface Observable<T> {
/**
* 进程内发送消息
*
* @param value 发送的消息
*/
void post(T value);
/**
* App内发送消息,跨进程使用
*
* @param value 发送的消息
*/
void postAcrossProcess(T value);
/**
* App之间发送消息
*
* @param value 发送的消息
*/
void postAcrossApp(T value);
/**
* 进程内发送消息,延迟发送
*
* @param value 发送的消息
* @param delay 延迟毫秒数
*/
void postDelay(T value, long delay);
/**
* 进程内发送消息,延迟发送,带生命周期
* 如果延时发送消息的时候sender处于非激活状态,消息取消发送
*
* @param sender 消息发送者
* @param value 发送的消息
* @param delay 延迟毫秒数
*/
void postDelay(LifecycleOwner sender, T value, long delay);
/**
* 进程内发送消息
* 强制接收到消息的顺序和发送顺序一致
*
* @param value 发送的消息
*/
void postOrderly(T value);
/**
* 以广播的形式发送一个消息
* 需要跨进程、跨APP发送消息的时候调用该方法
* 可使用postAcrossProcess or postAcrossApp代替
*
* @param value 发送的消息
*/
@Deprecated
void broadcast(T value);
/**
* 以广播的形式发送一个消息
* 需要跨进程、跨APP发送消息的时候调用该方法
*
* @param value 发送的消息
* @param foreground true:前台广播、false:后台广播
* @param onlyInApp true:只在APP内有效、false:全局有效
*/
void broadcast(T value, boolean foreground, boolean onlyInApp);
/**
* 注册一个Observer,生命周期感知,自动取消订阅
*
* @param owner LifecycleOwner
* @param observer 观察者
*/
void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer);
/**
* 注册一个Observer,生命周期感知,自动取消订阅
* 如果之前有消息发送,可以在注册时收到消息(消息同步)
*
* @param owner LifecycleOwner
* @param observer 观察者
*/
void observeSticky(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer);
/**
* 注册一个Observer,需手动解除绑定
*
* @param observer 观察者
*/
void observeForever(@NonNull Observer<T> observer);
/**
* 注册一个Observer,需手动解除绑定
* 如果之前有消息发送,可以在注册时收到消息(消息同步)
*
* @param observer 观察者
*/
void observeStickyForever(@NonNull Observer<T> observer);
/**
* 通过observeForever或observeStickyForever注册的,需要调用该方法取消订阅
*
* @param observer 观察者
*/
void removeObserver(@NonNull Observer<T> observer);
}
package com.sobot.widget.livedatabus.core;
public class ObservableConfig {
Boolean lifecycleObserverAlwaysActive = null;
Boolean autoClear = null;
/**
* lifecycleObserverAlwaysActive
* set if then observer can always receive message
* true: observer can always receive message
* false: observer can only receive message when resumed
*
* @param active boolean
* @return ObservableConfig
*/
public ObservableConfig lifecycleObserverAlwaysActive(boolean active) {
lifecycleObserverAlwaysActive = active;
return this;
}
/**
* @param clear boolean
* @return true: clear livedata when no observer observe it
* false: not clear livedata unless app was killed
*/
public ObservableConfig autoClear(boolean clear) {
autoClear = clear;
return this;
}
}
package com.sobot.widget.livedatabus.ipc.annotation;
import com.sobot.widget.livedatabus.ipc.core.Processor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IpcConfig {
Class<? extends Processor> processor();
}
package com.sobot.widget.livedatabus.ipc.consts;
public class IpcConst {
public static final String ACTION = "intent.action.ACTION_LEB_IPC";
public static final String KEY = "leb_ipc_key";
public static final String KEY_VALUE = "leb_ipc_value";
public static final String KEY_PROCESSOR_NAME = "leb_ipc_processor_name";
public static final String KEY_BUNDLE = "leb_ipc_bundle";
public static final String KEY_CLASS_NAME = "leb_ipc_class_name";
}
package com.sobot.widget.livedatabus.ipc.core;
import android.os.Bundle;
import com.sobot.widget.livedatabus.ipc.consts.IpcConst;
public class BooleanProcessor implements Processor {
@Override
public boolean writeToBundle(Bundle bundle, Object value) {
if (!(value instanceof Boolean)) {
return false;
}
bundle.putBoolean(IpcConst.KEY_VALUE, (boolean) value);
return true;
}
@Override
public Object createFromBundle(Bundle bundle) {
return bundle.getBoolean(IpcConst.KEY_VALUE);
}
}
package com.sobot.widget.livedatabus.ipc.core;
import android.os.Bundle;
import com.sobot.widget.livedatabus.ipc.consts.IpcConst;
public class DoubleProcessor implements Processor {
@Override
public boolean writeToBundle(Bundle bundle, Object value) {
if (!(value instanceof Double)) {
return false;
}
bundle.putDouble(IpcConst.KEY_VALUE, (Double) value);
return true;
}
@Override
public Object createFromBundle(Bundle bundle) {
return bundle.getDouble(IpcConst.KEY_VALUE);
}
}
package com.sobot.widget.livedatabus.ipc.core;
import android.os.Bundle;
import com.sobot.widget.livedatabus.ipc.consts.IpcConst;
public class FloatProcessor implements Processor {
@Override
public boolean writeToBundle(Bundle bundle, Object value) {
if (!(value instanceof Float)) {
return false;
}
bundle.putFloat(IpcConst.KEY_VALUE, (float) value);
return true;
}
@Override
public Object createFromBundle(Bundle bundle) {
return bundle.getFloat(IpcConst.KEY_VALUE);
}
}
package com.sobot.widget.livedatabus.ipc.core;
import android.os.Bundle;
import com.sobot.widget.livedatabus.ipc.consts.IpcConst;
public class IntProcessor implements Processor {
@Override
public boolean writeToBundle(Bundle bundle, Object value) {
if (!(value instanceof Integer)) {
return false;
}
bundle.putInt(IpcConst.KEY_VALUE, (int) value);
return true;
}
@Override
public Object createFromBundle(Bundle bundle) {
return bundle.getInt(IpcConst.KEY_VALUE);
}
}
package com.sobot.widget.livedatabus.ipc.core;
import android.os.Bundle;
import com.sobot.widget.livedatabus.ipc.consts.IpcConst;
public class LongProcessor implements Processor {
@Override
public boolean writeToBundle(Bundle bundle, Object value) {
if (!(value instanceof Long)) {
return false;
}
bundle.putLong(IpcConst.KEY_VALUE, (long) value);
return true;
}
@Override
public Object createFromBundle(Bundle bundle) {
return bundle.getLong(IpcConst.KEY_VALUE);
}
}
package com.sobot.widget.livedatabus.ipc.core;
import android.os.Bundle;
import android.os.Parcelable;
import com.sobot.widget.livedatabus.ipc.consts.IpcConst;
public class ParcelableProcessor implements Processor {
@Override
public boolean writeToBundle(Bundle bundle, Object value) {
if (!(value instanceof Parcelable)) {
return false;
}
bundle.putParcelable(IpcConst.KEY_VALUE, (Parcelable) value);
return true;
}
@Override
public Object createFromBundle(Bundle bundle) {
return bundle.getParcelable(IpcConst.KEY_VALUE);
}
}
package com.sobot.widget.livedatabus.ipc.core;
import android.os.Bundle;
public interface Processor {
boolean writeToBundle(Bundle bundle, Object value) throws Exception;
Object createFromBundle(Bundle bundle) throws Exception;
}
package com.sobot.widget.livedatabus.ipc.core;
import android.content.Intent;
import android.os.Bundle;
import com.sobot.widget.livedatabus.ipc.annotation.IpcConfig;
import com.sobot.widget.livedatabus.ipc.consts.IpcConst;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class ProcessorManager {
private static class SingletonHolder {
private static final ProcessorManager INSTANCE = new ProcessorManager();
}
public static ProcessorManager getManager() {
return SingletonHolder.INSTANCE;
}
private final List<Processor> baseProcessors;
private final Map<String, Processor> processorMap;
{
baseProcessors = new LinkedList<>(Arrays.asList(
new StringProcessor(),
new IntProcessor(),
new BooleanProcessor(),
new DoubleProcessor(),
new FloatProcessor(),
new LongProcessor(),
new SerializableProcessor(),
new ParcelableProcessor()));
processorMap = new HashMap<>();
for (Processor processor : baseProcessors) {
processorMap.put(processor.getClass().getName(), processor);
}
}
private ProcessorManager() {
}
public boolean writeTo(Intent intent, Object value) {
if (intent == null || value == null) {
return false;
}
Bundle bundle = new Bundle();
boolean processed = false;
//用指定的processor处理
IpcConfig config = value.getClass().getAnnotation(IpcConfig.class);
if (config != null) {
Class<? extends Processor> processorType = config.processor();
String processorTypeName = processorType.getName();
if (!processorMap.containsKey(processorTypeName)) {
try {
processorMap.put(processorTypeName, processorType.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
Processor processor = processorMap.get(processorTypeName);
if (processor != null) {
try {
boolean handle = processor.writeToBundle(bundle, value);
if (handle) {
intent.putExtra(IpcConst.KEY_PROCESSOR_NAME, processor.getClass().getName());
intent.putExtra(IpcConst.KEY_BUNDLE, bundle);
processed = true;
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (processed) {
return true;
}
}
//用默认的processor处理
for (Processor processor : baseProcessors) {
try {
boolean handle = processor.writeToBundle(bundle, value);
if (handle) {
intent.putExtra(IpcConst.KEY_PROCESSOR_NAME, processor.getClass().getName());
intent.putExtra(IpcConst.KEY_BUNDLE, bundle);
processed = true;
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return processed;
}
public Object createFrom(Intent intent) {
if (intent == null) {
return null;
}
String processorName = intent.getStringExtra(IpcConst.KEY_PROCESSOR_NAME);
Bundle bundle = intent.getBundleExtra(IpcConst.KEY_BUNDLE);
if (processorName == null || processorName.length() == 0 || bundle == null) {
return null;
}
if (!processorMap.containsKey(processorName)) {
try {
processorMap.put(processorName, (Processor) Class.forName(processorName).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
Processor processor = processorMap.get(processorName);
if (processor == null) {
return null;
}
try {
return processor.createFromBundle(bundle);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
package com.sobot.widget.livedatabus.ipc.core;
import android.os.Bundle;
import com.sobot.widget.livedatabus.ipc.consts.IpcConst;
import java.io.Serializable;
public class SerializableProcessor implements Processor {
@Override
public boolean writeToBundle(Bundle bundle, Object value) {
if (!(value instanceof Serializable)) {
return false;
}
bundle.putSerializable(IpcConst.KEY_VALUE, (Serializable) value);
return true;
}
@Override
public Object createFromBundle(Bundle bundle) {
return bundle.getSerializable(IpcConst.KEY_VALUE);
}
}
package com.sobot.widget.livedatabus.ipc.core;
import android.os.Bundle;
import com.sobot.widget.livedatabus.ipc.consts.IpcConst;
public class StringProcessor implements Processor {
@Override
public boolean writeToBundle(Bundle bundle, Object value) {
if (!(value instanceof String)) {
return false;
}
bundle.putString(IpcConst.KEY_VALUE, (String) value);
return true;
}
@Override
public Object createFromBundle(Bundle bundle) {
return bundle.getString(IpcConst.KEY_VALUE);
}
}
package com.sobot.widget.livedatabus.ipc.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.sobot.widget.livedatabus.SobotLiveEventBus;
import com.sobot.widget.livedatabus.ipc.consts.IpcConst;
import com.sobot.widget.livedatabus.ipc.core.ProcessorManager;
public class LebIpcReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (IpcConst.ACTION.equals(intent.getAction())) {
try {
String key = intent.getStringExtra(IpcConst.KEY);
Object value = ProcessorManager.getManager().createFrom(intent);
if (key != null && value != null) {
SobotLiveEventBus.get(key).post(value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
package com.sobot.widget.livedatabus.logger;
import android.util.Log;
import java.util.logging.Level;
public class DefaultLogger implements Logger {
private static final String TAG = "[LiveEventBus]";
@Override
public void log(Level level, String msg) {
if (level == Level.SEVERE) {
Log.e(TAG, msg);
} else if (level == Level.WARNING) {
Log.w(TAG, msg);
} else if (level == Level.INFO) {
Log.i(TAG, msg);
} else if (level == Level.CONFIG) {
Log.d(TAG, msg);
} else if (level != Level.OFF) {
Log.v(TAG, msg);
}
}
@Override
public void log(Level level, String msg, Throwable th) {
if (level == Level.SEVERE) {
Log.e(TAG, msg, th);
} else if (level == Level.WARNING) {
Log.w(TAG, msg, th);
} else if (level == Level.INFO) {
Log.i(TAG, msg, th);
} else if (level == Level.CONFIG) {
Log.d(TAG, msg, th);
} else if (level != Level.OFF) {
Log.v(TAG, msg, th);
}
}
}
package com.sobot.widget.livedatabus.logger;
import java.util.logging.Level;
public interface Logger {
void log(Level level, String msg);
void log(Level level, String msg, Throwable th);
}
package com.sobot.widget.livedatabus.logger;
import java.util.logging.Level;
public class LoggerManager implements Logger {
private Logger logger;
private boolean enable = true;
public LoggerManager(Logger logger) {
this.logger = logger;
}
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public Logger getLogger() {
return logger;
}
public void setLogger(Logger logger) {
this.logger = logger;
}
@Override
public void log(Level level, String msg) {
if (enable) {
logger.log(level, msg);
}
}
@Override
public void log(Level level, String msg, Throwable th) {
if (enable) {
logger.log(level, msg, th);
}
}
}
package com.sobot.widget.livedatabus.utils;
import android.os.Looper;
public final class ThreadUtils {
public static boolean isMainThread() {
return Looper.myLooper() == Looper.getMainLooper();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment