package com.android.pc.ioc.util; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import android.app.Activity; import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; import android.view.View; import com.android.pc.ioc.app.Ioc; import com.android.pc.ioc.core.kernel.KernelString; import com.android.pc.ioc.inject.InjectAll; import com.android.pc.ioc.inject.InjectBefore; import com.android.pc.ioc.inject.InjectBinder; import com.android.pc.ioc.inject.InjectHttp; import com.android.pc.ioc.inject.InjectHttpErr; import com.android.pc.ioc.inject.InjectHttpOk; import com.android.pc.ioc.inject.InjectInit; import com.android.pc.ioc.inject.InjectLayer; import com.android.pc.ioc.inject.InjectListener; import com.android.pc.ioc.inject.InjectMethod; import com.android.pc.ioc.inject.InjectOnNewIntent; import com.android.pc.ioc.inject.InjectPLayer; import com.android.pc.ioc.inject.InjectPause; import com.android.pc.ioc.inject.InjectPullRefresh; import com.android.pc.ioc.inject.InjectResource; import com.android.pc.ioc.inject.InjectRestart; import com.android.pc.ioc.inject.InjectResume; import com.android.pc.ioc.inject.InjectStart; import com.android.pc.ioc.inject.InjectStop; import com.android.pc.ioc.inject.InjectView; import com.android.pc.ioc.invoker.InjectHttps; import com.android.pc.ioc.invoker.InjectInvoker; import com.android.pc.ioc.invoker.InjectLayers; import com.android.pc.ioc.invoker.InjectMethods; import com.android.pc.ioc.invoker.InjectPLayers; import com.android.pc.ioc.invoker.InjectResources; import com.android.pc.ioc.invoker.InjectViews; import com.android.pc.ioc.invoker.InjectViews.Views; public class ContextUtils { /** ID_NONE */ public final static int ID_NONE = -1; /** ID_ZERO */ public final static int ID_ZERO = 0; /** 包括了 InjectLayer InjectView InjectBinder InjectResource InjectMethod InjectInit 的集合 */ private static final Map<Class<?>, InjectInvoker> all_inject_layers = new HashMap<Class<?>, InjectInvoker>(); private static final Map<Class<?>, ArrayList<InjectInvoker>> all_inject_views = new HashMap<Class<?>, ArrayList<InjectInvoker>>(); private static final Map<Class<?>, ArrayList<InjectInvoker>> orther_inject_invokes = new HashMap<Class<?>, ArrayList<InjectInvoker>>(); /** 包括了 有关activity生命周期 的 的集合 */ private static final Map<Class<?>, HashMap<Class<?>, ArrayList<InjectInvoker>>> lift_InjectInvokes = new HashMap<Class<?>, HashMap<Class<?>, ArrayList<InjectInvoker>>>(); /** 包括了网络请求的 的集合 */ private static final Map<Class<?>, HashMap<Integer, ArrayList<InjectInvoker>>> http_InjectInvokes = new HashMap<Class<?>, HashMap<Integer, ArrayList<InjectInvoker>>>(); private static final Map<Class<?>, HashMap<Integer, ArrayList<InjectInvoker>>> http_InjectInvokes_OK = new HashMap<Class<?>, HashMap<Integer, ArrayList<InjectInvoker>>>(); private static final Map<Class<?>, HashMap<Integer, ArrayList<InjectInvoker>>> http_InjectInvokes_Err = new HashMap<Class<?>, HashMap<Integer, ArrayList<InjectInvoker>>>(); private static final Map<Class<?>, Boolean> inject_status = new HashMap<Class<?>, Boolean>(); private static HashSet<Class<?>> classes = new HashSet<Class<?>>() { private static final long serialVersionUID = -2816879839908314497L; { add(Drawable.class); add(String.class); } }; public static ArrayList<InjectInvoker> getContextInvokers(Class<?> contextType, Class<?> method) { return lift_InjectInvokes.get(contextType).get(method); } public static ArrayList<InjectInvoker> getHttpAllInvokers(Class<?> contextType, int key) { if (!http_InjectInvokes.containsKey(contextType)) { return null; } HashMap<Integer, ArrayList<InjectInvoker>> hashMap = http_InjectInvokes.get(contextType); if (!hashMap.containsKey(key)) { return null; } return hashMap.get(key); } public static ArrayList<InjectInvoker> getHttpOkInvokers(Class<?> contextType, int key) { if (!http_InjectInvokes_OK.containsKey(contextType)) { return null; } HashMap<Integer, ArrayList<InjectInvoker>> hashMap = http_InjectInvokes_OK.get(contextType); if (!hashMap.containsKey(key)) { return null; } return hashMap.get(key); } public static ArrayList<InjectInvoker> getHttpErrInvokers(Class<?> contextType, int key) { if (!http_InjectInvokes_Err.containsKey(contextType)) { return null; } HashMap<Integer, ArrayList<InjectInvoker>> hashMap = http_InjectInvokes_Err.get(contextType); if (!hashMap.containsKey(key)) { return null; } return hashMap.get(key); } /** * 根据contextType 获取AfterCreate和BeforeCreate 等等 activity生命周期的反射 * * @author gdpancheng@gmail.com 2013-11-1 下午1:10:02 * @param contextType * @return * @return InjectInvoker[][] */ public static void getCreateInvokers(final Class<?> contextType) { HashMap<Class<?>, ArrayList<InjectInvoker>> injectInvokers = lift_InjectInvokes.get(contextType); if (injectInvokers != null) { return; } lift_InjectInvokes.put(contextType, new HashMap<Class<?>, ArrayList<InjectInvoker>>()); http_InjectInvokes.put(contextType, new HashMap<Integer, ArrayList<InjectInvoker>>()); http_InjectInvokes_OK.put(contextType, new HashMap<Integer, ArrayList<InjectInvoker>>()); http_InjectInvokes_Err.put(contextType, new HashMap<Integer, ArrayList<InjectInvoker>>()); Class<?> template = contextType; while (template != null && template != Object.class) { // 过滤掉基类 因为基类是不包含注解的 if (template.getName().equals("android.app.Activity") || template.getName().equals("android.support.v4.app.FragmentActivity") || template.getName().equals("android.support.v4.app.Fragment") || template.getName().equals("android.app.Fragment")) { break; } // --------------------------------------------------------------------------------------------- HashMap<Class<?>, ArrayList<InjectInvoker>> aInvokerLists = lift_InjectInvokes.get(contextType); HashMap<Integer, ArrayList<InjectInvoker>> https = http_InjectInvokes.get(contextType); HashMap<Integer, ArrayList<InjectInvoker>> https_ok = http_InjectInvokes_OK.get(contextType); HashMap<Integer, ArrayList<InjectInvoker>> https_err = http_InjectInvokes_Err.get(contextType); Method[] methods = template.getDeclaredMethods(); for (int j = 0; j < methods.length; j++) { Method method = methods[j]; if (method.getAnnotation(InjectBefore.class) != null) { if (!aInvokerLists.containsKey(InjectBefore.class)) { aInvokerLists.put(InjectBefore.class, new ArrayList<InjectInvoker>()); } aInvokerLists.get(InjectBefore.class).add(new InjectMethods(method, null, null, null)); } else if (method.getAnnotation(InjectOnNewIntent.class) != null) { if (!aInvokerLists.containsKey(InjectOnNewIntent.class)) { aInvokerLists.put(InjectOnNewIntent.class, new ArrayList<InjectInvoker>()); } aInvokerLists.get(InjectOnNewIntent.class).add(new InjectMethods(method, null, null, null)); } else if (method.getAnnotation(InjectPause.class) != null) { if (!aInvokerLists.containsKey(InjectPause.class)) { aInvokerLists.put(InjectPause.class, new ArrayList<InjectInvoker>()); } aInvokerLists.get(InjectPause.class).add(new InjectMethods(method, null, null, null)); } else if (method.getAnnotation(InjectResume.class) != null) { if (!aInvokerLists.containsKey(InjectResume.class)) { aInvokerLists.put(InjectResume.class, new ArrayList<InjectInvoker>()); } aInvokerLists.get(InjectResume.class).add(new InjectMethods(method, null, null, null)); } else if (method.getAnnotation(InjectRestart.class) != null) { if (!aInvokerLists.containsKey(InjectRestart.class)) { aInvokerLists.put(InjectRestart.class, new ArrayList<InjectInvoker>()); } aInvokerLists.get(InjectRestart.class).add(new InjectMethods(method, null, null, null)); } else if (method.getAnnotation(InjectStart.class) != null) { if (!aInvokerLists.containsKey(InjectStart.class)) { aInvokerLists.put(InjectStart.class, new ArrayList<InjectInvoker>()); } aInvokerLists.get(InjectStart.class).add(new InjectMethods(method, null, null, null)); } else if (method.getAnnotation(InjectStop.class) != null) { if (!aInvokerLists.containsKey(InjectStop.class)) { aInvokerLists.put(InjectStop.class, new ArrayList<InjectInvoker>()); } aInvokerLists.get(InjectStop.class).add(new InjectMethods(method, null, null, null)); } else if (method.getAnnotation(InjectHttp.class) != null) { InjectHttp injectHttp = method.getAnnotation(InjectHttp.class); int[] keys = injectHttp.value(); for (int i = 0; i < keys.length; i++) { if (!https.containsKey(keys[i])) { https.put(keys[i], new ArrayList<InjectInvoker>()); } https.get(keys[i]).add(new InjectHttps(method)); } } else if (method.getAnnotation(InjectHttpOk.class) != null) { InjectHttpOk injectHttp = method.getAnnotation(InjectHttpOk.class); int[] keys = injectHttp.value(); for (int i = 0; i < keys.length; i++) { if (!https_ok.containsKey(keys[i])) { https_ok.put(keys[i], new ArrayList<InjectInvoker>()); } https_ok.get(keys[i]).add(new InjectHttps(method)); } } else if (method.getAnnotation(InjectHttpErr.class) != null) { InjectHttpErr injectHttp = method.getAnnotation(InjectHttpErr.class); int[] keys = injectHttp.value(); for (int i = 0; i < keys.length; i++) { if (!https_err.containsKey(keys[i])) { https_err.put(keys[i], new ArrayList<InjectInvoker>()); } https_err.get(keys[i]).add(new InjectHttps(method)); } } } // --------------------------------------------------------------------------------------------- template = template.getSuperclass(); } } /** * 根据class获取当前类的所有注解 * * @author gdpancheng@gmail.com 2014-1-21 上午11:42:27 * @param clazz * @param obj * @param superClass * @return * @return ArrayList<InjectInvoker> */ @SuppressWarnings("unchecked") public static ArrayList<InjectInvoker> getViewInvokers(final Class<?> clazz, final Object obj, final Class<?> superClass) { // 集合里面有这个类的集合 那么就直接返回了 ArrayList<InjectInvoker> all_list = new ArrayList<InjectInvoker>(); ArrayList<InjectInvoker> layers_list = new ArrayList<InjectInvoker>(); ArrayList<InjectInvoker> views_list = new ArrayList<InjectInvoker>(); ArrayList<InjectInvoker> orther_list = new ArrayList<InjectInvoker>(); // ---------------------------------------------------------------------------------------------------------- Class<?> template = clazz; if (all_inject_layers.containsKey(clazz) && orther_inject_invokes.containsKey(clazz)&&checkInjectStatus(clazz)) { while (template != null && template != Object.class && template != superClass&&inject_status.containsKey(template)) { if (all_inject_layers.containsKey(template) && Activity.class.isAssignableFrom(template)) { layers_list.add(0, all_inject_layers.get(template)); } if (all_inject_views.containsKey(template) && Activity.class.isAssignableFrom(template)) { views_list.addAll(0, all_inject_views.get(template)); } if (orther_inject_invokes.containsKey(template) && Activity.class.isAssignableFrom(template)) { orther_list.addAll(0, orther_inject_invokes.get(template)); } template = template.getSuperclass(); } all_list.addAll(layers_list); all_list.addAll(views_list); all_list.addAll(orther_list); if (all_list.size() > 0) { return all_list; } } // ---------------------------------------------------------------------------------------------------------- template = clazz; // 为了记录存在下拉刷新的组件,也就是说一个页面只支持一个下拉刷新 InjectViews pull_down; while (template != null && template != Object.class && template != superClass) { // 过滤掉基类 因为基类是不包含注解的 if (template.getName().equals("android.app.Activity") || template.getName().equals("android.support.v4.app.FragmentActivity") || template.getName().equals("android.support.v4.app.Fragment")) { break; } // 重置为空 pull_down = null; // 用来存储每一个类的注解 ArrayList<InjectInvoker> local_list = new ArrayList<InjectInvoker>(); ArrayList<InjectInvoker> localview_list = new ArrayList<InjectInvoker>(); // 此变量是用来标注当前类是否是Activity的子类,因为只有Activity才需要setContentView // 另一种就是Fragment 这种情况下是不需要setContentView 所以要单独区分开来 boolean isActivity = false; if (obj == null || Activity.class.isAssignableFrom(obj.getClass())) { isActivity = true; } InjectLayer injectLayer = template.getAnnotation(InjectLayer.class); InjectLayers local_layers = null; // 如果是Activity 则把获取到的layout添加到集合中 if (isActivity && injectLayer != null && injectLayer.value() != ContextUtils.ID_ZERO) { local_layers = new InjectLayers(injectLayer.value(), injectLayer.isFull(), injectLayer.isTitle(), injectLayer.parent(), InjectViewUtils.Inject_Excutors[0]); } // 如果不是Activity 则是fragment 那么我们需要把当前的Object对象保持到集合中 因为它不是 // activity 所以不能通过Context.findbyid而只能通过 view.findbyid 当不是Activity的时候activity为fragment里面的view if (!isActivity) { local_layers = new InjectLayers(ContextUtils.ID_NONE, false, false, ContextUtils.ID_NONE, InjectViewUtils.Inject_Excutors[1].setObject(obj)); } InjectPLayer injectPLayer = template.getAnnotation(InjectPLayer.class); if (injectPLayer != null && layers_list.size() > 0) { InjectLayers injectLayers = (InjectLayers) layers_list.get(0); if (injectLayers.getParent() != ID_NONE) { InjectPLayers injectPLayers = new InjectPLayers(injectPLayer.value(), injectPLayer.isFull(), injectPLayer.isTitle(), InjectViewUtils.Inject_Excutors[0]); injectLayers.setInjectPLayers(injectPLayers); } } // 如果是Activity InjectLayer没有设置 则提示错误 if (isActivity && injectLayer == null && injectPLayer == null) { if (clazz == template) { Ioc.getIoc().getLogger().d(template + " 无法获取到对应layout的ID 请检查injectLayer或者injectPLayer是否设置\n"); } } // 获得当前类的所有的字段 Field[] fields = template.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; // 获取allview注解 InjectAll injectAll = field.getAnnotation(InjectAll.class); if (injectAll != null) { int id = 0; Class<?> type = field.getType(); InjectBinder inBinder = injectAll.value(); Field[] allFields = type.getDeclaredFields(); for (int j = 0; j < allFields.length; j++) { allFields[j].setAccessible(true); if (View.class.isAssignableFrom(allFields[j].getType())) { try { id = 0; id = InjectViewUtils.getResouceId("id", allFields[j].getName()); } catch (Exception e) { Ioc.getIoc().getLogger().e("内部类 " + template + " 变量 " + allFields[j].getName() + " 无法获取到对应的ID 请检查InjectView的参数\n"); } InjectViews injectViews = new InjectViews(id, isActivity ? InjectViewUtils.Inject_Excutors[0] : InjectViewUtils.Inject_Excutors[1].setObject(obj), allFields[j], false, false, false, type, field); InjectBinder injectBinder = allFields[j].getAnnotation(InjectBinder.class); if (injectBinder != null) { Views views = injectViews.new Views(injectBinder.method(), injectBinder.listeners()); injectViews.setViews(views); } else if (inBinder.method().length() > 0) { Views views = injectViews.new Views(inBinder.method(), inBinder.listeners()); injectViews.setViews(views); } if (clazz != template) { localview_list.add(0, injectViews); } else { localview_list.add(injectViews); } continue; } try { if (allFields[j].getType() == Drawable.class || allFields[j].getType() == String.class) { id = InjectViewUtils.getResouceId(KernelString.capitalize(allFields[j].getType().getSimpleName()), allFields[j].getName()); if (allFields[j].getType() == Drawable.class) { InjectResources injectResources = new InjectResources(id, allFields[j], InjectResouceSupply.injectResouceTypes[2], type, field); local_list.add(injectResources); } if (allFields[j].getType() == String.class) { InjectResources injectResources = new InjectResources(id, allFields[j], InjectResouceSupply.injectResouceTypes[0], type, field); local_list.add(injectResources); } } } catch (Exception e) { Ioc.getIoc().getLogger().e(template + " 变量" + allFields[j].getName() + "|" + allFields[j].getType() + "无法获取到对应的ID 请检查InjectView的参数\n"); e.printStackTrace(); } } } // 获取view注解 InjectView injectView = field.getAnnotation(InjectView.class); if (injectView != null) { int id = injectView.value(); // 如果注解为空 那么我们就根据名字取获取其id if (id == ContextUtils.ID_NONE) { try { id = InjectViewUtils.getResouceId("id", field.getName()); } catch (Exception e) { Ioc.getIoc().getLogger().e(template + " 变量" + field.getName() + "无法获取到对应的ID 请检查InjectView的参数\n"); e.printStackTrace(); } } // 判断listview 是否添加图片滑动停止加载 如果InjectView含有此参数 则表示使用 boolean isAsy = false; boolean pull = injectView.pull(); boolean down = injectView.down(); InjectViews injectViews = new InjectViews(id, isActivity ? InjectViewUtils.Inject_Excutors[0] : InjectViewUtils.Inject_Excutors[1].setObject(obj), field, isAsy, injectView.pull(), injectView.down(), null, null); if (pull || down) { pull_down = injectViews; } InjectBinder[] injectBinders = injectView.binders(); if (injectBinders != null) { for (InjectBinder injectBinder : injectBinders) { String method = injectBinder.method(); Class<?>[] classes = injectBinder.listeners(); Views views = injectViews.new Views(method, classes); injectViews.setViews(views); } // 这里是要保证父activity或者fragment的view的注入必须在子类之前 if (clazz != template) { localview_list.add(0, injectViews); } else { localview_list.add(injectViews); } continue; } } // 资源文件变量的绑定 目前只支持图片和字符串 InjectResource Inject = field.getAnnotation(InjectResource.class); if (Inject != null) { if (!classes.contains(field.getType())) { break; } int id = Inject.value(); if (id == ContextUtils.ID_NONE) { try { id = InjectViewUtils.getResouceId(KernelString.capitalize(field.getType().getSimpleName()), field.getName()); } catch (Exception e) { Ioc.getIoc().getLogger().e(template + " 变量" + field.getName() + "无法获取到对应的ID 请检查InjectView的参数\n"); e.printStackTrace(); } } if (field.getType() == Drawable.class) { InjectResources injectResources = new InjectResources(id, field, InjectResouceSupply.injectResouceTypes[2], null, null); local_list.add(injectResources); } if (field.getType() == String.class) { InjectResources injectResources = new InjectResources(id, field, InjectResouceSupply.injectResouceTypes[0], null, null); local_list.add(injectResources); } } } Method[] methods = template.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (pull_down != null) { InjectPullRefresh injectPullRefresh = method.getAnnotation(InjectPullRefresh.class); if (injectPullRefresh != null) { pull_down.setMethod(method); } } InjectMethod injectMethod = method.getAnnotation(InjectMethod.class); if (injectMethod != null) { InjectListener[] injectListener = injectMethod.value(); if (injectListener != null) { for (InjectListener injectInvoker : injectListener) { InjectMethods injectMethods = new InjectMethods(method, injectInvoker.ids(), injectInvoker.listeners(), isActivity ? InjectViewUtils.Inject_Excutors[0] : InjectViewUtils.Inject_Excutors[1].setObject(obj)); local_list.add(injectMethods); } } } InjectInit Inject = method.getAnnotation(InjectInit.class); if (Inject == null) { continue; } InjectMethods injectMethods = new InjectMethods(method, null, null, null); local_list.add(injectMethods); } if (local_layers != null) { layers_list.add(0, local_layers); all_inject_layers.put(template, local_layers); } views_list.addAll(localview_list); all_inject_views.put(template, localview_list); orther_list.addAll(0, local_list); orther_inject_invokes.put(template, local_list); template = template.getSuperclass(); } all_list.addAll(layers_list); all_list.addAll(views_list); all_list.addAll(orther_list); return all_list; } public static void getFactoryProvider() { PackageManager pManager = Ioc.getIoc().getApplication().getPackageManager(); Class<?>[] classes = null; try { PackageInfo packageInfo = pManager.getPackageInfo(Ioc.getIoc().getApplication().getPackageName(), PackageManager.GET_ACTIVITIES); ActivityInfo[] activityInfos = packageInfo.activities; classes = new Class[activityInfos.length]; for (int i = 0; i < activityInfos.length; i++) { ActivityInfo activityInfo = activityInfos[i]; try { classes[i] = Class.forName(activityInfo.name); } catch (ClassNotFoundException e) { continue; } } } catch (NameNotFoundException e) { } if (classes == null) { return; } for (int i = 0; i < classes.length; i++) { Class<?> clazz = classes[i]; inject_status.put(clazz, true); ContextUtils.getCreateInvokers(clazz); ContextUtils.getViewInvokers(clazz, null, Activity.class); inject_status.remove(clazz); } } public static boolean checkInjectStatus(Class<?> clazz) { if (inject_status.containsKey(clazz)) { return false; } return true; } }