1、视图

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
> <Button
android:id="@+id/btn_login"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="登陆" />
<Button
android:id="@+id/btn_register"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="注册" /> </LinearLayout>

2、MainActivity

 package com.zyh.zyh_ioc;

 import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button; import com.zyh.ioc.annotation.ContentView;
import com.zyh.ioc.annotation.OnClick;
import com.zyh.ioc.annotation.ViewInject;
import com.zyh_ioc.activity.BaseActivity;
import android.widget.Toast; @ContentView(R.layout.activity_main)
public class MainActivity extends BaseActivity {
@ViewInject(R.id.btn_login)
private Button btnLogin; @ViewInject(R.id.btn_register)
private Button btnRegister; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("zyh",btnLogin.getText().toString() + "," + btnRegister.getText().toString());
} @OnClick({R.id.btn_login,R.id.btn_register})
public void Toast(View btn){
switch(btn.getId()){
case R.id.btn_login:
Toast.makeText(this, "登陆", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_register:
Toast.makeText(this, "注册", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
}

3、BaseActivity

 package com.zyh_ioc.activity;

 import com.zyh.ioc.utils.InjectUtils;

 import android.app.Activity;
import android.os.Bundle; public class BaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
InjectUtils.inject(this);
}
}

4、InjectUtils

 package com.zyh.ioc.utils;

 import com.zyh.ioc.annotation.ContentView;
import com.zyh.ioc.annotation.EventBase;
import com.zyh.ioc.annotation.OnClick;
import com.zyh.ioc.annotation.ViewInject;
import com.zyh.ioc.proxy.ListenerInvocationHandler; import android.app.Activity;
import android.view.View; import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; //===============================================
//类的Annotation需要类对象来获取
//方法的Annotation需要方法对象来获取
//属性的Annotation需要属性对象来获取
//Annotation的Annotation需要Annotation的类对象来获取
//=============================================== public class InjectUtils {
public static void inject(Activity activity){
injectContentView(activity);
injectViews(activity);
injectEvents(activity);
} /**
* @desc 注入布局
* @param activity
*/
private static void injectContentView(Activity activity) {
Class<? extends Activity> clazz = activity.getClass();
ContentView contentView = clazz.getAnnotation(ContentView.class);
int layoutId = contentView.value();
activity.setContentView(layoutId);
} /**
* @desc 注入控件
* @param activity
*/
private static void injectViews(Activity activity) {
Class<? extends Activity> clazz = activity.getClass();
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields){
ViewInject viewInject = field.getAnnotation(ViewInject.class);
if(viewInject != null){
//获取注解上的值
int viewId = viewInject.value();
Object view = activity.findViewById(viewId);//获取视图对象
try {
field.setAccessible(true);//表明私有的属性也可以设置值
field.set(activity, view);//给属性设值
} catch (Exception e) {
e.printStackTrace();
}
}
}
} /**
* @desc 注入事件
* @param activity
*/
private static void injectEvents(Activity activity) {
Class<? extends Activity> clazz = activity.getClass();
Method[] methods = clazz.getMethods();
for(Method method : methods){
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation : annotations){
Class<? extends Annotation> annotationType = annotation.annotationType();//返回的是Annotation类对象
if(annotationType != null){
EventBase eventBase = annotationType.getAnnotation(EventBase.class);//获取注释的注释
if(eventBase != null){
String listenerSetter = eventBase.listenerSetter();//获取的设置监听事件的方法名
Class<?> listenerType = eventBase.listenerType();//获取监听事件的类对象
String methodName = eventBase.callBackMethod();//获取回调方法名 //下面两行代码说明:得到Annotation实例就可以获取annotation括号里的内容
/*OnClick onClick = (OnClick) annotation;
int[] xxx = onClick.value();*/
try {
//这里是利用反射获取viewIds的值
Method valueMethod = annotationType.getDeclaredMethod("value");
int[] viewIds = (int[]) valueMethod.invoke(annotation, null); //设置代理
ListenerInvocationHandler handler = new ListenerInvocationHandler(activity);
//onClick->toast
handler.addMethod(methodName, method);
//通过Proxy产生一个listenerType类型的代理对象
//listener是一个onClickListener对象
Object listener = Proxy.newProxyInstance(listenerType.getClassLoader(), new Class<?>[]{listenerType}, handler); //多个按钮要注册监听
for(int viewId : viewIds){
View view = activity.findViewById(viewId); //获取setOnClickListener方法
Method setter = view.getClass().getMethod(listenerSetter, listenerType);
//注册
setter.invoke(view, listener);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
}

5、自定义的Annotation

1)布局的Annotation

 package com.zyh.ioc.annotation;

 import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; //指定注解使用的类的位置上
@Target(ElementType.TYPE) //编译程序将注解存储在class文件中,让虚拟机通过反射读入
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
int value();
}

2)findViewById的Annotation

 package com.zyh.ioc.annotation;

 import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; //指定使用在属性上
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME)
public @interface ViewInject {
int value();
}

3)点击事件的Annotation

 package com.zyh.ioc.annotation;

 import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import android.view.View; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventBase(listenerSetter = "setOnClickListener",listenerType = View.OnClickListener.class,callBackMethod = "onClick")
public @interface OnClick {
int[] value();
}
 package com.zyh.ioc.annotation;

 import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; //说明在另外的注解上使用
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventBase {
/**
* @desc 例如:setOnClickListener的方法名称
* @return
*/
String listenerSetter(); /**
* @desc 说明listener的类型
* @return
*/
Class<?> listenerType(); /**
* @desc listener的回调方法名称
* @return
*/
String callBackMethod();
}

6、代理类

 package com.zyh.ioc.proxy;

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap; public class ListenerInvocationHandler implements InvocationHandler {
private Object target; private HashMap<String, Method> methodMap = new HashMap<String, Method>(); public ListenerInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(target != null){
//执行的方法名称onClick
String methodName = method.getName();
//toast方法
Method method2 = methodMap.get(methodName);
if(method2 != null){
method2.invoke(target, args);
}
}
return null;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
} /**
* @desc 绑定方法
* @param name
* @param method
*/
public void addMethod(String name, Method method){
methodMap.put(name, method);
}
}

代理的理解可以参考:http://blog.csdn.net/rokii/article/details/4046098

ioc构架demo的更多相关文章

  1. 话说IOC(DI)

    什么是IOC(DI) 书上的东东,因为说的太严谨,所以不太容易懂,其实也没那么复杂. 举几个例子: 1.文明点的:中午太热,不想出去吃饭,所以希望同事能帮忙带饭,现在有了点外卖平台,我们就可以直接在网 ...

  2. spring的IOC/DI功能实践

    一.写在前面: 做这个Demo主要是为了能够更好的理解Spring的原理,看再多的文章,听再多的讲解最终都最好自己去实现一遍,可以将Spring的功能分块实现,最终自然比较容易将各个功能组合起来. 这 ...

  3. Spring入门IOC和AOP学习笔记

    Spring入门IOC和AOP学习笔记 概述 Spring框架的核心有两个: Spring容器作为超级大工厂,负责管理.创建所有的Java对象,这些Java对象被称为Bean. Spring容器管理容 ...

  4. Spring.Net控制翻转、依赖注入、面向切面编程

    Spring.Net快速入门:控制翻转.依赖注入.面向切面编程 Spring.Net主要功能: 1.IoC:控制翻转(Inversion of Control)  理解成抽象工厂翻转控制:就是创建对象 ...

  5. Spring.Net快速入门:控制翻转、依赖注入、面向切面编程

    Spring.Net主要功能: 1.IoC:控制翻转(Inversion of Control)  理解成抽象工厂翻转控制:就是创建对象的权利由开发人员自己控制New,转到了由容器来控制. 2.DI: ...

  6. java后端开发三年!你还不了解Spring 依赖注入,凭什么给你涨薪

    前言 前两天和一个同学吃饭的时候同学跟我说了一件事,说他公司有个做了两年的人向他提出要涨薪资,他就顺口问了一个问题关于spring依赖注入的,那个要求涨薪的同学居然被问懵了...事后回家想了想这一块确 ...

  7. IOC:AutoFac使用demo

    使用autofac 实现依赖注入 1.引用 autofac.dll 和 autofac.configuration.dll 2.新增接口 IDAL using System; using System ...

  8. 学习Spring框架系列(一):通过Demo阐述IoC和DI的优势所在

    Spring框架最核心东西便是大名鼎鼎的IoC容器,主要通过DI技术实现.下面我通过Demo的演变过程,对比学习耦合性代码,以及解耦和的过程,并深入理解面向接口编程的真正内涵. 这个例子包括如下几个类 ...

  9. Spring之IOC/DI(反转控制/依赖注入)_入门Demo

    在平时的java应用开发中,我们要实现某一个功能或者说是完成某个业务逻辑时至少需要两个或以上的对象来协作完成,在没有使用Spring的时候,每个对象在需要使用他的合作对象时,自己均要使用像new ob ...

随机推荐

  1. PLSQL 导入表到Oracle------》从一个表空间导入到其它表空间

        在用PLSQL导入.dmp文件到Oracle时出现的问题如下: Import started on 2015/11/18 10:42:44E:\oracle\product\10.2.0\db ...

  2. How to access the properties of an object in Javascript

    Javascript has three different kinds of properties: named data property, named accessor property and ...

  3. C标准函数库中获取时间与日期、对时间与日期数据操作及格式化

    表示时间的三种数据类型[编辑] 日历时间(calendar time),是从一个标准时间点(epoch)到现在的时间经过的秒数,不包括插入闰秒对时间的调整.开始计时的标准时间点,各种编译器一般使用19 ...

  4. Difference between LINQ to SQL and LINQ to Entity(DataContext and DbContext)

    http://msdn.microsoft.com/en-us/library/cc161164.aspx http://stackoverflow.com/questions/2443836/wha ...

  5. BCS--设置BDC元数据存储权限--访问被业务数据拒绝

    设置元数据存储权限 http://blog.163.com/liangshan_wei@126/blog/static/8297850320139126930290/

  6. 基于表单的身份验证(FBA)

    https://technet.microsoft.com/zh-cn/library/ee806890(office.15).aspx http://www.tuicool.com/articles ...

  7. LINQ 图解

    LINQ 图解 原创地址:http://www.cnblogs.com/jfzhu/archive/2013/01/01/2841332.html 转载请注明出处 LINQ,语言集成查询(Langua ...

  8. ADO.NET基础笔记

    ADO.NET 程序要和数据库交互要通过ADO.NET进行,通过ADO.Net就能在程序中执行SQL了. ADO.Net中提供了对各种不同的数据库的统一操作接口. 连接字符串: 程序通过连接字符串指定 ...

  9. CSS3 transform制作的漂亮的滚动式导航

    模拟这个做的 不过实现的没有别人那么好 http://www.creativetier.com/products/modern-menu-3/vertical.html 关于transform  看这 ...

  10. 第二节 EAN 8 码 / EAN 13 码

    EAN码的全名为欧洲商品条码(European Article Number),源於西元1977年,由欧洲十二个工业国家所共同发展出来的一种条码.目前已成为一种国际性的条码系统.EAN条码系统的管理是 ...