Android IOC 动态代理实现

先贴上所有代码



布局文件



xml version="1.0" encoding="utf-8"?>
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="anmin.calendar.xiaomi.proxxy.MainActivity">

    



使用代理的Activity

package anmin.calendar.xiaomi.proxxy;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.AppCompatButton;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity{
    @ViewInject(R.id.one)
    Button one;
    @ViewInject(R.id.two)
    Button two;
    @ViewInject(R.id.three)
    Button three;
    @ViewInject(R.id.four)
    Button four;
    @ViewInject(R.id.five)
    Button five;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        InjectView.ViewInject(this);
        InjectView.InjectView(this);
        one.setText("ONE");
        two.setText("TWO");
        three.setText("THREE");
        four.setText("Four");
        five.setText("FIVE");
    }
    @Event(id ={R.id.one,R.id.two,R.id.three,R.id.four,R.id.five},
    enventType = View.OnClickListener.class)
    private void click(View pView){
        Toast.makeText(this,"成功点击",Toast.LENGTH_LONG).show();
        if (pView instanceof AppCompatButton){
            Button btn= (Button) pView;
            Toast.makeText(this,btn.getText().toString(),Toast.LENGTH_LONG).show();
        }
    }
}



setContentView注解类



package anmin.calendar.xiaomi.proxxy;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by Administrator on 2016/11/18.
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ContentView {
    int value();
}


findViewbyid注解类



package anmin.calendar.xiaomi.proxxy;

import android.renderscript.Sampler;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.xml.validation.Validator;

/**
 * Created by Administrator on 2016/11/18.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ViewInject
{
   int value();
}


实现点击事件的注解类




package anmin.calendar.xiaomi.proxxy;

import android.view.View;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by Administrator on 2016/11/18.
 */
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Event {
    int[] id();
    Class enventType() default View.OnClickListener.class;
}


实现注解功能的类


setContentView和findViewbyid都是通过反射方式来实现的,比较简单。

package anmin.calendar.xiaomi.proxxy;
import android.app.Activity;
import android.view.View;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * Created by Administrator on 2016/11/18.
 */
public class InjectView {
    private final  static String onClick=View.OnClickListener.class.getSimpleName();
    private final static String onLongClick=View.OnLongClickListener.class.getSimpleName();

    public static void   ViewInject(Activity pActivity){
        if (pActivity!=null){
            Classextends Activity> cls = pActivity.getClass();
            if (cls.isAnnotationPresent(ContentView.class)){
                ContentView lContentView=cls.getAnnotation(ContentView.class);
                int layoutId=lContentView.value();
                pActivity.setContentView(layoutId);
                InjectView.setClick(pActivity);
            }
        }
    }


    public static void setClick(Activity activity){
        if (activity!=null){
            Classextends Activity> cls = activity.getClass();
            Method[] method = cls.getDeclaredMethods();
            for (Method m : method){
                if (m.isAnnotationPresent(Event.class)){
                    Event lEvent=m.getAnnotation(Event.class);
                    int[] ids=lEvent.id();
                    Class css=lEvent.enventType();
                    String name=css.getSimpleName();
                    try{
                        for (int id :ids){
                        if (name.equals(onClick)){
                            View lView=activity.findViewById(id);
                            MyInvocationHandler handler=new MyInvocationHandler();
                            handler.setView(lView);
                            handler.setMethod(m);
                            handler.setActivity(activity);
                            Classextends View> cl = lView.getClass();
                            Method lMethod=cl.getMethod("setOnClickListener",new Class[]{View.OnClickListener.class});
                            Object proxy = Proxy.newProxyInstance(lEvent.enventType().getClassLoader(),
                                    new Class[]{lEvent.enventType()},handler);
                            lMethod.setAccessible(true);
                            lMethod.invoke(lView,proxy);

                        }
                    }
                    }
                    catch (Exception e){

                    }
                        if (name.equals(onLongClick)){
                        }


                }
            }


        }
    }

    public static void InjectView(Activity pActivity){
        if (pActivity!=null){
            Classextends Activity> cls = pActivity.getClass();
            Field[] field = cls.getFields();
            for (Field f :field){
                if (f.isAnnotationPresent(ViewInject.class)){
                    ViewInject lViewInject=f.getAnnotation(ViewInject.class);
                    int viewId=lViewInject.value();
                    View v=pActivity.findViewById(viewId);
                    f.setAccessible(true);
                    try {
                        f.set(pActivity,v);
                    } catch (IllegalAccessException pE) {
                        pE.printStackTrace();
                    }
                }
            }


        }


    }
}


实现点击事件主要设计到两个类即InvocationHandler和Proxy来动态实现点击事件接口的代理。

package anmin.calendar.xiaomi.proxxy;
import android.app.Activity;
import android.view.View;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * Created by Administrator on 2016/11/18.
 */
public class MyInvocationHandler implements InvocationHandler {
    private Method mMethod;
    private View mView;
    private Activity mActivity;

    public void setActivity(Activity pActivity) {
        mActivity = pActivity;
    }

    public Method getMethod() {
        return mMethod;
    }

    public void setMethod(Method pMethod) {
        mMethod = pMethod;
    }

    public View getView() {
        return mView;
    }

    public void setView(View pView) {
        mView = pView;
    }

    @Override
    public Object invoke(Object pO, Method pMethod, Object[] pObjects) throws Throwable {
        mMethod.setAccessible(true);
        
        return mMethod.invoke(mActivity,pObjects);
    }
}




你可能感兴趣的:(android-主题)