Skip to content

Commit

Permalink
完成sdk获取注册,懒加载
Browse files Browse the repository at this point in the history
  • Loading branch information
YummyLau committed Aug 13, 2019
1 parent 52e537e commit 8972c59
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 66 deletions.
2 changes: 1 addition & 1 deletion app/src/main/java/com/plugin/component/MainActivity.java
Expand Up @@ -34,7 +34,7 @@ public void onClick(View view) {
.setAction("Action", null).show();
}
});
((TextView) findViewById(R.id.text)).setText(SdkManager.getService(IAction.class).getName());
((TextView) findViewById(R.id.text)).setText(SdkManager.getSdk(IAction.class).getName());
}

@Override
Expand Down
30 changes: 25 additions & 5 deletions core/src/main/java/com/plugin/component/ComponentInfo.java
Expand Up @@ -11,14 +11,34 @@ public ComponentInfo(Class componentClass) {
this.componentClass = componentClass;
}

public ComponentInfo(IComponent componentObject) {
this.componentClass = componentObject.getClass();
this.componentObject = componentObject;
public ComponentInfo(IComponent componentImpl) {
this.componentClass = componentImpl.getClass();
this.componentImpl = componentImpl;
}

public Class componentClass;
public IComponent componentObject;
public ArrayMap<Class, Class> sdkMap;
public IComponent componentImpl;

private ArrayMap<Class, Object> sdkMap = new ArrayMap<>();


public void registerSdk(Class sdkClass, Object sdkImpl) {
sdkMap.put(sdkClass, sdkImpl);
}

public boolean unregisterSdk(Class sdkKey) {
if (sdkMap.containsKey(sdkKey)) {
sdkMap.remove(sdkKey);
return true;
}
return false;
}

public boolean hasSdk(Class sdkKey) {
return sdkMap.containsKey(sdkKey);
}

public Object getSdk(Class sdkKey) {
return sdkMap.get(sdkKey);
}
}
91 changes: 72 additions & 19 deletions core/src/main/java/com/plugin/component/ComponentManager.java
Expand Up @@ -2,11 +2,12 @@

import android.app.Application;
import android.util.ArrayMap;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.lang.ref.WeakReference;
import java.util.Set;

/**
* 组件管理
Expand All @@ -16,48 +17,88 @@
*/
public class ComponentManager {

private static final String TAG = "component-core";

private static Application sApplication;
private static ArrayMap<Class, ComponentInfo> sComponentInfoArrayMap;

public ComponentInfo findSdk() {
public static Application getApplication() {
return sApplication;
}

public static void setApplication(Application sApplication) {
ComponentManager.sApplication = sApplication;
}

public static ComponentInfo findComponentInfoBySdk(Class sdkKey) {
if (sComponentInfoArrayMap == null) {
return null;
}
Set<Class> classes = sComponentInfoArrayMap.keySet();
for (Class clazz : classes) {
ComponentInfo componentInfo = sComponentInfoArrayMap.get(clazz);
if (componentInfo.hasSdk(sdkKey)) {
return componentInfo;
}
}
return null;
}


public static ComponentInfo hasRegister(@NonNull Object componentObjectOrClass) {
boolean isComponentImplClass = componentObjectOrClass instanceof Class;
Class realComponentClass = isComponentImplClass ? (Class) componentObjectOrClass : componentObjectOrClass.getClass();
return sComponentInfoArrayMap.get(realComponentClass);
}


/**
* 注册组件实现累必须实现 IComponent
*
* @param componentObjectOrClass 支持 class 类型 或者 object 类型
* @param componentImplObjectOrClass 支持 class 类型 或者 object 类型
* class 类型用于自动注册或者获取sdk时懒初始化
* object 类型用于手动注册,不支持 sdk 加载时再懒初始化
*/
public static void registerComponent(@NonNull Object componentObjectOrClass) {
public static ComponentInfo registerComponent(@NonNull Object componentImplObjectOrClass) {
Class componentClass = IComponent.class;

if (componentObjectOrClass.getClass().isInterface()) {
if (componentImplObjectOrClass.getClass().isInterface()) {
throw new IllegalArgumentException("register component object must not be interface.");
}

boolean isComponentImplClass = componentObjectOrClass instanceof Class;
boolean isComponentImplClass = componentImplObjectOrClass instanceof Class;

Class realClass = isComponentImplClass ? (Class) componentObjectOrClass : componentObjectOrClass.getClass();
Class realClass = isComponentImplClass ? (Class) componentImplObjectOrClass : componentImplObjectOrClass.getClass();

if (!componentClass.isAssignableFrom(realClass)) {
throw new IllegalArgumentException(String.format("register service object must implement interface %s.", componentClass));
throw new IllegalArgumentException(String.format("register component object must implement interface %s.", componentClass));
}

if (sComponentInfoArrayMap == null) {
sComponentInfoArrayMap = new ArrayMap<>();
}

if (isComponentImplClass) {
ComponentInfo componentInfo = new ComponentInfo((Class) componentObjectOrClass);
sComponentInfoArrayMap.put(realClass, componentInfo);
ComponentInfo componentInfo = sComponentInfoArrayMap.get(realClass);
if (componentInfo != null) {
//如果已经存在当时未初始化且当前覆盖的为实现类
if (componentInfo.componentImpl == null && !isComponentImplClass) {
componentInfo.componentImpl = (IComponent) componentImplObjectOrClass;
componentInfo.componentImpl.attachComponent(sApplication);
sComponentInfoArrayMap.put(realClass, componentInfo);
Log.d(TAG, String.format("register component[ %s ] success, with object that overriding class, doing attachComponent ", realClass));
}
} else {
ComponentInfo componentInfo = new ComponentInfo((IComponent) componentObjectOrClass);
componentInfo.componentObject.attachComponent(sApplication);
sComponentInfoArrayMap.put(realClass, componentInfo);
if (isComponentImplClass) {
componentInfo = new ComponentInfo((Class) componentImplObjectOrClass);
sComponentInfoArrayMap.put(realClass, componentInfo);
Log.d(TAG, String.format("register component[ %s ] success, with class", realClass));
} else {
componentInfo = new ComponentInfo((IComponent) componentImplObjectOrClass);
componentInfo.componentImpl.attachComponent(sApplication);
sComponentInfoArrayMap.put(realClass, componentInfo);
Log.d(TAG, String.format("register component[ %s ] success, with object", realClass));
}
}
return componentInfo;
}

/**
Expand All @@ -69,20 +110,32 @@ public static void registerComponent(@NonNull Object componentObjectOrClass) {
*/
public static <T extends IComponent> boolean unregisterComponent(@NonNull Class<T> component) {
if (sComponentInfoArrayMap == null) {
Log.d(TAG, String.format("unregister component[ %s ] fail, sComponentInfoArrayMap is null.", component));
return false;
}
ComponentInfo componentInfo = sComponentInfoArrayMap.get(component);
if (componentInfo == null) {
Log.d(TAG, String.format("unregister component[ %s ] fail, didn't register %s.", component, component));
return false;
}
if (componentInfo.componentObject != null) {
componentInfo.componentObject.detachComponent();
if (componentInfo.componentImpl != null) {
componentInfo.componentImpl.detachComponent();
Log.d(TAG, String.format("unregister component[ %s ] success, doing detachComponent", component));
} else {
Log.d(TAG, String.format("unregister component[ %s ] success", component));
}
sComponentInfoArrayMap.remove(component);
return false;
}


/**
* 获取组件,如果组件未初始化,则需要初始化组件
*
* @param component
* @param <T>
* @return
*/
@Nullable
public static <T extends IComponent> IComponent getComponent(@NonNull Class<T> component) {
if (sComponentInfoArrayMap == null) {
Expand All @@ -92,15 +145,15 @@ public static <T extends IComponent> IComponent getComponent(@NonNull Class<T> c
if (componentInfo == null) {
return null;
}
IComponent result = componentInfo.componentObject;
IComponent result = componentInfo.componentImpl;
//如果已经初始化,则直接返回
if (result != null) {
return result;
} else {
try {
result = (IComponent) componentInfo.componentClass.newInstance();
result.attachComponent(sApplication);
componentInfo.componentObject = result;
componentInfo.componentImpl = result;
return result;
} catch (IllegalAccessException e) {
e.printStackTrace();
Expand Down
99 changes: 58 additions & 41 deletions core/src/main/java/com/plugin/component/SdkManager.java
@@ -1,70 +1,87 @@
package com.plugin.component;

import android.util.ArrayMap;
import android.util.Log;

import androidx.annotation.NonNull;

import java.lang.ref.WeakReference;

import androidx.annotation.Nullable;

public class SdkManager {

private static ArrayMap<Class, Object> sServiceArrayMap;
private static ArrayMap<Class, WeakReference<Object>> sWeekServiceArrayMap;
private static final String TAG = "component-core";

public static void register(@NonNull Class serviceKey, @NonNull Object serviceObjectOrClass) {
if (!serviceKey.isInterface()) {
public static void register(@NonNull Object componentObjectOrClass, @NonNull Class sdkKey, @NonNull Object sdkImplObjectOrClass) {
ComponentInfo componentInfo = ComponentManager.hasRegister(componentObjectOrClass);
if (componentInfo == null) {
componentInfo = ComponentManager.registerComponent(componentObjectOrClass);
}
if (!sdkKey.isInterface()) {
throw new IllegalArgumentException("register service key must be interface class.");
}
if (serviceObjectOrClass.getClass().isInterface()) {
if (sdkImplObjectOrClass.getClass().isInterface()) {
throw new IllegalArgumentException("register service object must not be interface.");
}

Class realClass = serviceObjectOrClass instanceof Class ? (Class) serviceObjectOrClass : serviceObjectOrClass.getClass();

if (!serviceKey.isAssignableFrom(realClass)) {
throw new IllegalArgumentException(String.format("register service object must implement interface %s.", serviceKey));
Class realComponentClass = sdkImplObjectOrClass instanceof Class ? (Class) sdkImplObjectOrClass : sdkImplObjectOrClass.getClass();
Class realImplClass = sdkImplObjectOrClass instanceof Class ? (Class) sdkImplObjectOrClass : sdkImplObjectOrClass.getClass();
if (!sdkKey.isAssignableFrom(realImplClass)) {
throw new IllegalArgumentException(String.format("register service object must implement interface %s.", sdkKey));
}

if (sServiceArrayMap == null) {
sServiceArrayMap = new ArrayMap<>();
}
sServiceArrayMap.put(serviceKey, serviceObjectOrClass);
Log.d(TAG, String.format("register sdk[ %s ] in component[ %s ] success, with %s", sdkKey, realComponentClass, realImplClass));
componentInfo.registerSdk(sdkKey, sdkImplObjectOrClass);
}

public static void unregister(Class serviceKey) {
if (serviceKey == null || sServiceArrayMap == null) return;
sServiceArrayMap.remove(serviceKey);
public static void unregister(Class sdkKey) {
ComponentInfo componentInfo = ComponentManager.findComponentInfoBySdk(sdkKey);
if (componentInfo != null) {
componentInfo.unregisterSdk(sdkKey);
Log.d(TAG, String.format("unregister sdk[ %s ] success, component[ %s ] remove it.", sdkKey, componentInfo.componentClass));
return;
}
Log.d(TAG, String.format("unregister sdk[ %s ] fail, no component has it.", sdkKey));
}

@Nullable
public static <T> T getSdk(Class<T> sdkKey) {
ComponentInfo componentInfo = ComponentManager.findComponentInfoBySdk(sdkKey);
if (componentInfo != null) {
Object result;
if (componentInfo.componentImpl == null) {
try {
componentInfo.componentImpl = (IComponent) componentInfo.componentClass.newInstance();
componentInfo.componentImpl.attachComponent(ComponentManager.getApplication());
Log.d(TAG, String.format("before getting sdk[ %s ] , component[ %s ] doing attachComponent.", sdkKey, componentInfo.componentClass));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}

public static <T> T getService(Class<T> serviceKey) {
if (sServiceArrayMap == null) return null;

Object object = sServiceArrayMap.get(serviceKey);
if (object == null) return null;

if (object instanceof Class) {
Object result = null;
if (sWeekServiceArrayMap == null) {
sWeekServiceArrayMap = new ArrayMap<>();
if (componentInfo.componentImpl == null) {
Log.d(TAG, String.format("before getting sdk[ %s ] , component[ %s ] init fail.", sdkKey, componentInfo.componentClass));
return null;
}
WeakReference<Object> cachedObject = sWeekServiceArrayMap.get(serviceKey);
if (cachedObject != null && cachedObject.get() != null) {
result = cachedObject.get();
} else {

result = componentInfo.getSdk(sdkKey);
if (result instanceof Class) {
try {
result = ((Class) object).newInstance();
sWeekServiceArrayMap.put(serviceKey, new WeakReference<>(result));
result = ((Class) result).newInstance();
componentInfo.registerSdk(sdkKey, result);
Log.d(TAG, String.format("before getting sdk[ %s ] , newInstance for sdk success.", sdkKey));
Log.d(TAG, String.format("get sdk[ %s ] success. ", result.getClass()));
return (T) result;
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
return (T) result;
} else {
return (T) object;
if (result == null || result instanceof Class) {
Log.d(TAG, String.format("get sdk[ %s ] fail. ", sdkKey));
} else {
Log.d(TAG, String.format("get sdk[ %s ] success. ", result.getClass()));
}
}
Log.d(TAG, String.format("get sdk[ %s ] fail, no component has it.", sdkKey));
return null;
}
}

0 comments on commit 8972c59

Please sign in to comment.