Android 通过动态代理设置事件监听

下面通过 java 动态代理跟反射 动态为控件设置监听,配合注解可以实现类似bufferkrnif的依赖注入(简单点说就是不通过对View设置监听,直接回调指定的方法)
这里只分析 事件注入原理不涉及注解
对java动态代理不是很熟悉的请看:这里:http://blog.csdn.net/lqb3732842/article/details/58695219

思路步骤:
1:通过反射获得Veiw 的setOnclicListen
2:通过反射获得真实需要被回调的方法
3:创建一个动态代理,并且持有真实对象以及真实回调方法
4:绑定动态代理
5:通过反射调用第一步中的方法(这里就实现了View的setOnClickListener)
6:当view被点击后 会进入到代理处理类中,在代理处理类会回调真实的方法

实现代码Act

/**
 * 动态代理实现事件注入(原理)
 * 05
 * qq:799135138
 */
public class MainActivity extends AppCompatActivity {

    private Button bt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt = (Button) findViewById(R.id.bt);
        proxySetOnclick();
    }

    //通过代理为button设置监听
    private void proxySetOnclick() {
        try {
            //反射获得Button的setOnclicListen方法(参数1:方法名;2:方法参数类)
            Method setOnClickListener = bt.getClass().getMethod("setOnClickListener", View.OnClickListener.class);
            //获得真实回调的方法(后期可以用注解获得这里hardCode了)
            Method realClick=this.getClass().getMethod("realClick",View.class);
            //创建一个代理
            ProxyHandle handle = new ProxyHandle(this, realClick);
            //设置代理 返回的是对应的接口 (OnClickListener实例对象)
            Object proxyObj = Proxy.newProxyInstance(View.OnClickListener.class.getClassLoader(), new Class[]{View.OnClickListener.class}, handle);

            //调用对应View的设置监听方法 之后会到代理handle里去(对象可以用注解获得这里暂不分析)
            setOnClickListener.invoke(bt,proxyObj);

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    //真实回调方法
    public void realClick(View v) {
        Toast.makeText(this,"点击了",Toast.LENGTH_SHORT).show();
    }
}

代理处理代码:

/**
 * Created by 05 on 2017/3/1.
 * qq:799135138
 */

public class ProxyHandle implements InvocationHandler {
    private Object realObj;
    private Method realMethod;

    public ProxyHandle(Object realObj,Method realMethod){
        this.realObj=realObj;
        this.realMethod=realMethod;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //如果真实对象跟方法都不为null 则直接返回真是方法(这里真实方法必须跟接口方法参数保存一致)
        if (realObj!=null&&realMethod!=null){
           return realMethod.invoke(realObj,args);
        }else {
            return method.invoke(proxy,args);
        }
    }
}

效果,全程没设置监听,点击后回调指定方法:
这里写图片描述

DEMO:http://download.csdn.net/detail/lqb3732842/9767548

猜你喜欢

转载自blog.csdn.net/lqb3732842/article/details/59114355
今日推荐