本框架可以在Activity和Dialog中使用,并且已有代码示例。fragment读者自己加上就可以了,没写代码

package com.example.lsn_34;import android.app.Activity;
import android.os.Bundle;public class BaseActivity  extends Activity{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//多态,继承BaseActivity类的类就不用重写了。InjectUtils.inject(this);}
}
package com.example.lsn_34;import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;/*** Created by david on 2017/8/21.*/public class BaseDialog   extends Dialog {public BaseDialog(@NonNull Context context) {super(context);}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);InjectUtils.inject(this);}}
package com.example.lsn_34;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 ContentView {//调用该方法就可以拿到MainActivity上面注解,即:@ContentView(R.layout.activity_main) 中的括号内的内容int value();
}
package com.example.lsn_34;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*** 相当于java父类,*/
@Retention(RetentionPolicy.RUNTIME)
//该注解在另外一个注解上使用
@Target(ElementType.ANNOTATION_TYPE)
public @interface EventBase {
//  setOnClickListener  订阅String  listenerSetter();//    事件以及他的类型/*** 事件监听的类型* @return*/Class<?> listenerType();/*** 事件处理* @return*/String callbackMethod();}
package com.example.lsn_34;import android.view.View;import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//注入工具类,相当于我们的女朋友,负责找资源,把找到的资源交给Activity类。
public class InjectUtils {
//这个方法给Activity用public  static  void inject(Object context){//注入布局injectLayout(context);//注入组件injectView(context);//注入事件injectClick(context);}/*** 事件注入,事件注入比较复杂,因为android的事件不只一种。既要知道是哪一个控件,也要知道是哪一个事件* 已OnCLick事件为例,我们分析下事件的三个要素* textView.setOnClickListener(new View.OnClickListener() {*           @Override*            public void onClick(View v) {*            }*       });*       事件源:TextView*       事件:new View.OnClickListener()*       事件处理:onClick*   每个要素都要单独提取出来*  另外有事件的订阅setOnClickListenner();*/private static void injectClick(Object context) {//拿到ActivityClass<?> clazz=context.getClass();//拿到该Activity所有的方法,然后遍历所有的方法,看看哪个方法有相关注解Method[] methods=clazz.getDeclaredMethods();for (Method method:methods){
//            OnClick onClick = method.getAnnotation(OnClick.class);//这就写死了,不具备通用性//得到方法上的所有注解Annotation[] annotations = method.getAnnotations();for (Annotation annotation : annotations) {//                annotation  ===OnClick  OnClick.class//得到注解的种类Class<?> annotionClass=annotation.annotationType();//是否能得到@EventBase的注解EventBase eventBase = annotionClass.getAnnotation(EventBase.class);//如果没有eventBase,则表示当前方法不是一个处理事件的方法if(eventBase==null){continue;}//开始获取事件处理的相关信息,即三要素// 用于确定是哪种事件(onClick还是onLongClick)以及由谁来处理//订阅String listenerSetter=eventBase.listenerSetter();//事件(事件监听的类型)Class<?> listenerType=eventBase.listenerType();//事件处理   事件被触发之后,执行的回调方法的名称String callBackMethod=eventBase.callbackMethod();
/*** 拿到三要素之后,我们就想办法执行这个事件*  textView.setOnClickListener(new View.OnClickListener() {*                               @Override*                               public void onClick(View v) {**                               }*                           });*      listenerSetter和callBackMethod是两个字符串,需要通过反射得到,同时要反射得到textView*///                int[] value1=OnClick.value();//这就写死了Method valueMethod= null;try {//反射得到ID,再根据ID号得到对应的VIEWvalueMethod = annotionClass.getDeclaredMethod("value");//得到在Activity的方法中标示的所有的ID,如@OnLongClick({R.id.app_text,R.id.app_text1})int[] viewId= (int[]) valueMethod.invoke(annotation);//每一个ID都需要事件绑定for (int id : viewId) {Method findViewById=clazz.getMethod("findViewById",int.class);View view= (View) findViewById.invoke(context,id);if(view==null){continue;}//得到ID对应的VIEW以后//开始在这个VIEW上执行监听,使用动态代理,将代码转移到Activity上的onClick(添加自定义注解的方法)上////activity==context       click==methodListenerInvocationHandler listenerInvocationHandler = new ListenerInvocationHandler(context, method);//proxy======View.OnClickListener()对象Object proxy=Proxy.newProxyInstance(listenerType.getClassLoader(), new Class[]{listenerType}, listenerInvocationHandler);//执行方法                                   setOnClickListener,new View.OnClickListener()Method onClickMethod = view.getClass().getMethod(listenerSetter, listenerType);onClickMethod.invoke(view, proxy);}} catch (Exception e) {e.printStackTrace();}}}}/*** 控件注入* @param context*/private static void injectView(Object context) {//拿到对应的ActivityClass<?> aClass=context.getClass();//拿到所有的成员变量,然后一一判断,判断哪些字段添加了 @ViewInject(R.id.app_text)注解Field[] fields=aClass.getDeclaredFields();//遍历成员变量for (Field field:fields){ViewInject viewInject = field.getAnnotation(ViewInject.class);if (viewInject != null) {int valueId = viewInject.value();try {Method method=aClass.getMethod("findViewById",int.class);View view = (View) method.invoke(context, valueId);
//                    View view= mainActivity.findViewById(valueId);field.setAccessible(true);//Activity身上的字段field等于view即:context.field = view;field.set(context,view);} catch (Exception e) {e.printStackTrace();}}}}/*** 布局注入* @param context*/private static void injectLayout(Object context) {int layoutId=0;//要注入的布局ID//拿到MainActivity上面的注解,即:@ContentView(R.layout.activity_main)/***我们知道在Java中一切都是对象,我们一般所使用的对象都直接或间接继承自Object类。Object类中包含一个方法名叫  getClass,利用这个方法就可以获得一个实例的类型类。类型类指的是代表一个类型的类,因为一切皆是对象,类型也不例外,在Java使用类型类来表示一个类型。所有的类型类都是Class类的实例。**/Class<?> clazz=context.getClass();ContentView contentView = clazz.getAnnotation(ContentView.class);if (contentView != null) {//得到Activity类的注解@ContentView(R.layout.activity_main)中括号内的信息layoutId = contentView.value();try {//反射执行setContentView.//int.class:参数是整数// getMethod方法则根据方法名称和相关参数,来定位需要查找的Method对象并返回。Method method = context.getClass().getMethod("setContentView", int.class);//context 参数:实例化后的对象method.invoke(context, layoutId);} catch ( Exception e) {e.printStackTrace();}}}
}
package com.example.lsn_34;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** 代理类* 代理下面这段代码*     public boolean click(View view) {*     }*     主体是Activity,要执行的是click动作*/
public class ListenerInvocationHandler implements InvocationHandler {//     OnClickListener  1
//    MainActivity   2private Object activity;//要执行的方法private  Method activityMethod;public ListenerInvocationHandler(Object activity, Method activityMethod) {this.activity = activity;this.activityMethod = activityMethod;}/***按钮点下去就执行这个方法*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//在这里去调用被注解了的click()return activityMethod.invoke(activity,args);}
}
package com.example.lsn_34;import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;@ContentView(R.layout.activity_main)
public class MainActivity extends BaseActivity {@ViewInject(R.id.app_text)private Button textView;private Button textView1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Deprecated@OnClick({R.id.app_text,R.id.app_text1})public boolean click(View view) {Toast.makeText(this,"---->"+textView,Toast.LENGTH_SHORT).show();NewsDialog newsDialog = new NewsDialog(this);newsDialog.show();return false;}@OnLongClick({R.id.app_text,R.id.app_text1})public boolean longClick(View view) {Toast.makeText(this, "长按了", Toast.LENGTH_SHORT).show();return true;}
}
package com.example.lsn_34;import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;/*** Created by david on 2017/8/21.*/
@ContentView(R.layout.dialog_news)
public class NewsDialog extends BaseDialog {@ViewInject(R.id.dialogBtn)Button dialogBtn;public NewsDialog(@NonNull Context context) {super(context);}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Toast.makeText(getContext(), "dialogBtn "+dialogBtn, Toast.LENGTH_SHORT).show();}@OnClick(R.id.dialogBtn)public void click(View view) {Toast.makeText(getContext(), "  dialog点击啦", Toast.LENGTH_SHORT).show();}@Overridepublic void show() {super.show();/*** 设置宽度全屏,要设置在show的后面*/WindowManager.LayoutParams layoutParams = getWindow().getAttributes();layoutParams.gravity= Gravity.BOTTOM;layoutParams.width= WindowManager.LayoutParams.MATCH_PARENT;layoutParams.height= WindowManager.LayoutParams.WRAP_CONTENT;getWindow().getDecorView().setPadding(0, 0, 0, 0);getWindow().setAttributes(layoutParams);}
}
package com.example.lsn_34;import android.view.View;import com.example.lsn_34.EventBase;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.METHOD)//注解写在方法上
@EventBase(listenerSetter = "setOnClickListener", listenerType = View.OnClickListener.class, callbackMethod = "onClick")
public @interface OnClick {int[] value() default -1;
}
package com.example.lsn_34;import android.view.View;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.METHOD)
@EventBase(listenerSetter = "setOnLongClickListener", listenerType = View.OnLongClickListener.class, callbackMethod = "onLongClick")
public @interface OnLongClick {int[] value() default -1;
}
package com.example.lsn_34;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** Created by david on 24/2/2017.*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)//写到成员变量上面
public @interface ViewInject {int value();
}

王学岗移动架构34——IOC注入框架设计相关推荐

  1. android 播放器架构,Android播放器框架设计系列-1

    视频播放器框架已经非常成熟了,但是由于项目需求各种各样,第三方库使用起来需要大量修改定制,并且还会出现各种问题,因此把之前项目中开发的模块提取出来进行完善扩展,写了一套自研的播放框架,并且引入Jetp ...

  2. 移动架构-图片加载框架设计

    图片加载核心就那些东西,这里设计一个图片加载框架,涉及到本地加载和网络加载,内存缓存和硬盘缓存,等等 思路 在getView的时候开始框架的调用 配置一系列环境,包括加载策略,缓存策略,线程数量 调用 ...

  3. ASP.NET Core技术研究-探秘依赖注入框架

    ASP.NET Core在底层内置了一个依赖注入框架,通过依赖注入的方式注册服务.提供服务.依赖注入不仅服务于ASP.NET Core自身,同时也是应用程序的服务提供者. 毫不夸张的说,ASP.NET ...

  4. 自己来实现一套IOC注解框架

    我们自己来实现一套IOC注解框架吧,采用的方式反射加注解和Xutils类似,但我们尽量不写那么麻烦,也不打算采用动态代理,我们扩展一个检测网络的注解,比如没网的时候我们不去执行方法而是给予没有网络的提 ...

  5. Android 依赖注入框架 Dagger2使用

    前言 Dagger 2这个匕首确实很难上手,上手后又比较难瞬间掌握,可以这么说,刚开始使用就是用来尝(zhuang)鲜(X)的,但相信随着使用的加深,会不断体会到它对于整个项目架构的极强辅助作用,能使 ...

  6. 深入浅出依赖注入框架Dagger2

    目录 目录 依赖注入 依赖注入实现的三种方式 1. 构造注入 2. 属性注入 3. 接口注入 Dagger2 Dagger2的引入 不带Module的Inject方式(Inject+Component ...

  7. .net企业级架构实战之1——框架综述

    近日由于业务需要,接触了一些Flex下的东西,比如Mate框架(一个集成MVC和IOC的框架,其事件广播机制很强大),疏于整理spring.net学习资料,现在终于得闲,将心得梳理一下: spring ...

  8. 依赖注入框架Dagger2详解(一),依赖注入和控制反转的深入理解

    IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合.更优良的程序,而Dagger2框架是依赖注入思想践行者的优秀代表. 依赖注入框架Dagger2详解(一), ...

  9. .NET框架设计(高级框架架构模式)—钝化程序、逻辑冻结、冻结程序的延续、瞬间转移

    1]开篇介绍 这一篇文章我早准备写的,迟迟未写的原因是它过于抽象不太容易表达,也很难掌握:之前对它的理解还处于比较简单的功能性上,但是最近随着对领域驱动设计及架构的研究,设计思想有了一个提升对它的理解 ...

最新文章

  1. Android:FragmentTransaction
  2. Shell中NR/NF的意义
  3. UML作业第五次:分析系统,绘制状态图
  4. python装饰器函数-Python函数装饰器常见使用方法实例详解
  5. Java遍历Map的4种方式
  6. python-9:nonlocal,指定上一级变量
  7. from表单iframe原网页嵌入
  8. python 报ImportError: Install xlrd = 1.0.0 for Excel support错误出现及其解决帮法
  9. 查看html元素绑定的事件与方法 visual Event 插件
  10. ueditor上传大容量视频报http请求错误的解决方法
  11. cesium 文本标注被遮挡_Cesium-知识点(Viewer)
  12. Fluentd: Open Source Log Management
  13. UEditor 百度Web编辑器 - JSP版本的使用
  14. 一级计算机office选择题题库及答案,计算机一级msoffice选择题题库40套含答案
  15. 使用3DMM进行人脸重建中的配准方法
  16. 笔记本(宏基4741G)升级为固态硬盘
  17. JDK动态代理和CGLIB动态代理
  18. vant 个人中心头像修改
  19. baidumap 判断是否安装百度地图客户端
  20. 昌平二中2021高考成绩查询喜报,北京2021高考成绩排名榜单,北京各高中高考成绩喜报...

热门文章

  1. 几种Web服务器比较-(Apache、IIS、Lighttpd、Nginx、LiteSpeed、Zeus
  2. 项目中使用 husky 配合 lint-staged 进行git提交前代码检查
  3. “JEPG”到“TXT”,魔幻的Loot
  4. ADP论文关键要点总结
  5. 基于区块链的去中心化身份技术有哪些应用前景?
  6. db2经典SQL语句大全
  7. 测测你的IQ加分析能力
  8. Arduino使用ESP8266安装问题(包括附加开发板管理网址)
  9. STM32连接WIFI-ESP8266获取天气信息---STA模式运用
  10. 微信为什么要绑定银行卡?