国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

IOC框架手動實現

2019-11-08 00:37:21
字體:
來源:轉載
供稿:網友

流行的注解框架是butterknife,使用注解框架主要是為了提高編碼效率,盡可能地少寫findviewbyid這種重復代碼。注解分為編譯期注解和運行時注解,butterknife是編譯期注解,接下來自己實現的該框架是運行時注解。編譯期注解有難度,并且不會對性能有影響。 Android中的注解反射框架包含三個部分: 1、Layout布局注解;2、view注解;3、事件注解。 框架建立分析如下: 該框架的目標是自動化下面3個工作: 1、Layout的注解解決的是activity的this.setContentView(R.layout.mainLayout),所以layout的注解的值只需要傳遞一個int值,同時需要將context對象傳進去,那么其注解類設計如下:

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface InjectLayout { int value();}

具體的方法:

PRivate static void injectLayout(Context context) throws NoSuchMethodException, InvocationTargetException, IllegalaccessException { Class clazz = context.getClass(); Method mtd_setContentView = clazz.getMethod("setContentView", int.class); Method mtd_findViewById = clazz.getMethod("findViewById", int.class); Annotation layoutAnnotation = clazz.getAnnotation(InjectLayout.class); if (layoutAnnotation != null && layoutAnnotation instanceof InjectLayout) { int layoutId = ((InjectLayout) layoutAnnotation).value(); mtd_setContentView.invoke(context, layoutId); }}

在Activity中的用法:

@InjectLayout(value=R.layout.activity_main)public class MainActivity extends BaseActivity {}

2、View注解,實現的是this.findViewById(R.id.xxx),所以其注解類只需要傳遞一個整型的id值。注解類設計如下:

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface InjectView { int value();}

具體的方法:

private static void injectView(Context context) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Class clazz = context.getClass(); Field[] fields = clazz.getDeclaredFields(); Method mtd_findViewById = clazz.getMethod("findViewById", int.class); for (Field field : fields) { Annotation[] annotations = field.getAnnotations(); for (Annotation annotation : annotations) { if (annotation instanceof InjectView) { int viewId = ((InjectView) annotation).value(); field.setAccessible(true); View view = (View) mtd_findViewById.invoke(context, viewId); field.set(context, view); } } }}

在activity中的用法:

@InjectView(value = R.id.button) Button myBtn;

3、方法的注解。其實指的是事件監聽的注解,其形式為:

view.setOnClickListener(new View.OnClickListener(){ Public void onClick(View view){ Xxxx; } });

或者view.setOnLongClickListener();還有view.setOnTouchListener()等等 因為這個里面有匿名內部類,所以需要使用到動態代理。為了實現這個方法,需要知道是哪個view來綁定監聽,所以注解需要包含R.id.xxx;需要知道監聽的是view 的哪個方法,所以需要一個string來表示具體的方法名(匿名內部類listener實現的方法);在實現動態代理時,還需要知道匿名內部類的全類名,所以也需要一個Class;所以其注解類設計如下

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@EventBus(value = 1)public @interface InjectOnClick { String onClickListener(); String onClickMethod(); String bindListerMethod(); int[] bindViewId(); Class type();}

注解實現方法:

private static void injectOnClick(Context context) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, InstantiationException { Class clazz = context.getClass(); Method[] methods = clazz.getDeclaredMethods(); if (null == methods || methods.length == 0) return; HashMap<String, Method> methodMap = new HashMap<>(); for (Method method : methods) { //method:onClickText Annotation[] annotations = method.getAnnotations(); if (null == annotations || annotations.length == 0) continue; for (Annotation annotation : annotations) if (annotation instanceof InjectOnClick) { String onClickName = ((InjectOnClick) annotation).onClickMethod(); methodMap.put(onClickName, method); int[] viewIds = ((InjectOnClick) annotation).bindViewId(); for (int viewId : viewIds) { //Annotation eventBus = (Annotation)annotation.annotationType(); Method mtd_findViewById = clazz.getMethod("findViewById", int.class); //獲取VIEW View view = (View) mtd_findViewById.invoke(context, viewId); Log.d(TAG, "injectOnClick: " + ""); //Class clazz_annoymous = Class.forName("android.view.View.OnClickListener"); Method setOnclickListener = view.getClass().getMethod(((InjectOnClick) annotation).bindListerMethod(), ((InjectOnClick) annotation).type()); Class clz = ((InjectOnClick) annotation).type(); //動態代理 XutilsInvocationHandler handler = new XutilsInvocationHandler(context, methodMap);//該類繼承InvocationHandler. Object proxy = (Proxy) Proxy.newProxyInstance(context.getClassLoader(), new Class[]{clz}, handler); setOnclickListener.invoke(view, proxy); } } } }

在activity中的使用方法:

@InjectOnClick(onClickListener = "View.OnClickListener",bindListerMethod ="setOnClickListener", onClickMethod ="onClick",bindViewId = {R.id.button},type = View.OnClickListener.class) public void onButtonClick(View view){//此處的參數view,不能省略。 Log.d("liudong", "onClick: "); Toast.makeText(this,"BUTTON 被點擊了",Toast.LENGTH_SHORT).show(); }

總體的使用方式是,新建一個BaseActivity extends Activity,在其onCreate()中,依次實現layout view onClick的注解。 public void onCreate(){ InjectUtils.injectLayout(this); InjectUtils.injectView(this); InjectUtils.injectOnClick(this); } 然后后續的Activity都繼承該BaseActivity.


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 体育| 江西省| 含山县| 彰化县| 延津县| 利辛县| 舟山市| 清涧县| 江城| 瑞昌市| 自治县| 石渠县| 孟州市| 军事| 甘孜县| 酉阳| 新乡县| 黄龙县| 家居| 瑞昌市| 博乐市| 新竹市| 白朗县| 永州市| 宜兴市| 宜春市| 衡山县| 井陉县| 德化县| 呈贡县| 北宁市| 洛南县| 庆云县| 平定县| 原阳县| 平湖市| 巴林右旗| 临朐县| 克东县| 阳新县| 鄄城县|