mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Introducing nucleus
This commit is contained in:
		| @@ -17,6 +17,7 @@ import timber.log.Timber; | ||||
| public class App extends Application { | ||||
|  | ||||
|     AppComponent mApplicationComponent; | ||||
|     ComponentReflectionInjector<AppComponent> mComponentInjector; | ||||
|  | ||||
|     @Override | ||||
|     public void onCreate() { | ||||
| @@ -27,6 +28,9 @@ public class App extends Application { | ||||
|                 .appModule(new AppModule(this)) | ||||
|                 .build(); | ||||
|  | ||||
|         mComponentInjector = | ||||
|                 new ComponentReflectionInjector<>(AppComponent.class, mApplicationComponent); | ||||
|  | ||||
|         //ACRA.init(this); | ||||
|     } | ||||
|  | ||||
| @@ -38,6 +42,14 @@ public class App extends Application { | ||||
|         return mApplicationComponent; | ||||
|     } | ||||
|  | ||||
|     public ComponentReflectionInjector<AppComponent> getComponentReflection() { | ||||
|         return mComponentInjector; | ||||
|     } | ||||
|  | ||||
|     public static ComponentReflectionInjector<AppComponent> getComponentReflection(Context context) { | ||||
|         return get(context).getComponentReflection(); | ||||
|     } | ||||
|  | ||||
|     public static AppComponent getComponent(Context context) { | ||||
|         return get(context).getComponent(); | ||||
|     } | ||||
|   | ||||
| @@ -0,0 +1,97 @@ | ||||
| package eu.kanade.mangafeed; | ||||
|  | ||||
| import java.lang.reflect.Method; | ||||
| import java.util.HashMap; | ||||
| import java.util.concurrent.ConcurrentHashMap; | ||||
|  | ||||
| /** | ||||
|  * This class allows to inject into objects through a base class, | ||||
|  * so we don't have to repeat injection code everywhere. | ||||
|  * | ||||
|  * The performance drawback is about 0.013 ms per injection on a very slow device, | ||||
|  * which is negligible in most cases. | ||||
|  * | ||||
|  * Example: | ||||
|  * <pre>{@code | ||||
|  * Component { | ||||
|  *     void inject(B b); | ||||
|  * } | ||||
|  * | ||||
|  * class A { | ||||
|  *     void onCreate() { | ||||
|  *         componentReflectionInjector.inject(this); | ||||
|  *     } | ||||
|  * } | ||||
|  * | ||||
|  * class B extends A { | ||||
|  *     @Inject MyDependency dependency; | ||||
|  * } | ||||
|  * | ||||
|  * new B().onCreate() // dependency will be injected at this point | ||||
|  * | ||||
|  * class C extends B { | ||||
|  * | ||||
|  * } | ||||
|  * | ||||
|  * new C().onCreate() // dependency will be injected at this point as well | ||||
|  * }</pre> | ||||
|  * | ||||
|  * @param <T> a type of dagger 2 component. | ||||
|  */ | ||||
| public final class ComponentReflectionInjector<T> { | ||||
|  | ||||
|     private final Class<T> componentClass; | ||||
|     private final T component; | ||||
|     private final HashMap<Class<?>, Method> methods; | ||||
|  | ||||
|     public ComponentReflectionInjector(Class<T> componentClass, T component) { | ||||
|         this.componentClass = componentClass; | ||||
|         this.component = component; | ||||
|         this.methods = getMethods(componentClass); | ||||
|     } | ||||
|  | ||||
|     public T getComponent() { | ||||
|         return component; | ||||
|     } | ||||
|  | ||||
|     public void inject(Object target) { | ||||
|  | ||||
|         Class targetClass = target.getClass(); | ||||
|         Method method = methods.get(targetClass); | ||||
|         while (method == null && targetClass != null) { | ||||
|             targetClass = targetClass.getSuperclass(); | ||||
|             method = methods.get(targetClass); | ||||
|         } | ||||
|  | ||||
|         if (method == null) | ||||
|             throw new RuntimeException(String.format("No %s injecting method exists in %s component", target.getClass(), componentClass)); | ||||
|  | ||||
|         try { | ||||
|             method.invoke(component, target); | ||||
|         } | ||||
|         catch (Exception e) { | ||||
|             throw new RuntimeException(e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static final ConcurrentHashMap<Class<?>, HashMap<Class<?>, Method>> cache = new ConcurrentHashMap<>(); | ||||
|  | ||||
|     private static HashMap<Class<?>, Method> getMethods(Class componentClass) { | ||||
|         HashMap<Class<?>, Method> methods = cache.get(componentClass); | ||||
|         if (methods == null) { | ||||
|             synchronized (cache) { | ||||
|                 methods = cache.get(componentClass); | ||||
|                 if (methods == null) { | ||||
|                     methods = new HashMap<>(); | ||||
|                     for (Method method : componentClass.getMethods()) { | ||||
|                         Class<?>[] params = method.getParameterTypes(); | ||||
|                         if (params.length == 1) | ||||
|                             methods.put(params[0], method); | ||||
|                     } | ||||
|                     cache.put(componentClass, methods); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return methods; | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user