在Android上打造属于自己的Rxjava框架(二)调度器

来源:互联网 发布:中标软件地址 编辑:程序博客网 时间:2024/06/07 07:43

前言:上一篇架构了Rx的基础,这次我们来动手写一下调度器,对应RxJava的Schedule,个人认为对于android来说,调度器的加入是重中之重。对于Android来说异步处理一直是在编码上是一个扰乱代码结构的因素,Handler的编写常常让人头疼。


调度器内容我是直接没看Rxjava的实现,以前也“山寨“过EventBus,XUtils觉得用注解比较美观方便,所以把SubscribeOn换成了注解看上去更简洁一点。还可以单独控制每个目标方法的运行线程。


1.首先是抽象出一个直接调用的Abstarct类。

public abstract class IInvokeDirect<T>{    protected T proxy;    public void setProxy(T t){        proxy = t;    }    public abstract <V> V invoke(String methodname,Object... pars);}
T代表的是调用实体类的类型由于一个实体类中可以有多个目标方法,所以以methodname作为判断依据。
public class PublisherInvoker extends IInvokeDirect<OnPublisher>{    @Override    public <V> V invoke(String methodname, Object... pars) {        proxy.call((OnObserver) pars[0]);        return null;    }}
OnPublish的实现。无返回值有一个参数

public class ObserverInvoker extends IInvokeDirect<OnObserver>{    @Override    public <V> V invoke(String methodname, Object... pars) {        V res = null;        switch (methodname){            case "onFinished":                proxy.onFinished();                break;            case "onSuccess":                proxy.onSuccess(pars[0]);                break;            case "onError":                proxy.onError((Throwable) pars[0]);                break;        }        return res;    }}
OnObserver的实现内含三个目标方法
public class Function1Invoker<I,O> extends IInvokeDirect<Func1<I,O>> {    @Override    public <O> O invoke(String methodname, Object... pars) {        O ret = (O) proxy.call((I) pars[0]);        return ret;    }}
Func1的实现这是单参数+返回值调用的抽象
2.讲完直接调用接下来就是调度器主体
首先是Runnable实现类,这是必要的。封装了方法调用和掩饰
public class ProxyEntity implements Runnable{    private Method method;    private Object object;    private Object[] args;    private Object ret;    private int delay = 0;    public ProxyEntity(Method method, Object object, Object... args) {        this.method = method;        this.object = object;        this.args = args;    }    public void setDelay(int delay) {        this.delay = delay;    }    @Override    public void run() {        if (delay!=0){            try {                Thread.currentThread().sleep(delay);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        Invoker.invoke_direct(method,object,args);    }}

(1).invoke_direct分发器 分发各种直接调用。
public static <T> T invoke_direct(Method method, Object object, Object... values){        String name = method.getName();        IInvokeDirect invoke = null;        if (object instanceof OnObserver){            invoke = new ObserverInvoker();            invoke.setProxy(object);        }else if (object instanceof OnPublisher){            invoke = new PublisherInvoker();            invoke.setProxy(object);        }else if (object instanceof Func1){            invoke = new Function1Invoker();            invoke.setProxy(object);        }        if (invoke == null)            return null;        Object ret = invoke.<T>invoke(name,values);        if (ret == null)            return null;        return (T) ret;    }
通过instanceof分发调用实体
 (2).调度的种类 分装在emun中
public enum RunContextType {    MainThread,    MainLoop,    NewThread,    NewHandlerThread,    CurrentThread,    CurrentLoop,    IO,    Calculate,    Dynamic,    Custome;}
可以看到种类还是很多的,下面一个个来看 有点多
1).CurrentThread在当前线程调用,注意这里加入了delay
private <T> T invoke_current_thread(Method method, Object object,int delay,Object... values) {        if (delay!=0) {            try {                Thread.currentThread().sleep(delay);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        return invoke_direct(method, object, values);    }
2).CurrentLoop当前线程的消息队列
private void invoke_current_loop(Method method, Object object,int delay, Object... values) {        Looper looper = Looper.myLooper();        if (looper == null)            throw new RuntimeException(Thread.currentThread().getName()+"不是HandlerThread");        Handler handler = new Handler(looper);        ProxyEntity entity = new ProxyEntity(method,object,values);        if (delay == 0)            handler.post(entity);        else            handler.postDelayed(entity,delay);    }
注意当前线程如果不是hanlerthread则会抛出RunTime异常
3).MainThread主线程非常重要的一个
private void invoke_main_thread(Method method, Object object,int delay,Object... values) {        Looper mianLoop = Looper.getMainLooper();        ProxyEntity entity = new ProxyEntity(method,object,values);        if (Looper.myLooper() != Looper.getMainLooper()){            invoke_main_loop(method, object,delay,values);        }else {            invoke_current_thread(method, object, delay, values);        }    }
4).MainLoop主线程消息队列,和MainThread其实有些不同,体现在调用时机上,MainLoop在MainThread的调用时机靠后。
private void invoke_main_loop(Method method, Object object,int delay,Object... values) {        ProxyEntity entity = new ProxyEntity(method,object,values);        if (delay == 0)            mainHandler.post(entity);        else            mainHandler.postDelayed(entity,delay);    }
5).NewThread,新线程。
private void invoke_new_thread(Method method, Object object,int delay,Object... values) {        ProxyEntity entity = new ProxyEntity(method,object,values);        entity.setDelay(delay);        new Thread(entity).start();    }
6).IO,IO专用线程,是一个单队列的线程池,这个还有待商榷,具体实现继承在我的框架里
private void invoke_io(Method method, Object object,int delay,Object... values) {        ProxyEntity entity = new ProxyEntity(method,object,values);        entity.setDelay(delay);        MySigleThreadQueue.AddTask(entity);    }
7).Calculate,计算专用线程,是一个并发数为CPU核心数的线程池,适合密集型计算
private void invoke_calculate(Method method, Object object,int delay,Object... values) {        ProxyEntity entity = new ProxyEntity(method,object,values);        entity.setDelay(delay);        MyWorkThreadQueue.AddTask(entity);    }
8).NewHandlerThread,新的HandlerThread
private void invoke_new_handler_thread(Method method, Object object,int delay,Object... values) {        ProxyEntity entity = new ProxyEntity(method,object,values);        HandlerThread thread = new HandlerThread(object.getClass().getName()+method.getName());        thread.start();        Handler handler = new Handler(thread.getLooper());        if (delay == 0)            handler.post(entity);        else            handler.postDelayed(entity,delay);    }
3.调度方法的分发器,根据方法体上的注解分发
public void invoke(Method method, Object object, Object... values){        RunContext runContext = method.getAnnotation(RunContext.class);        RunContextType type;        int delay = 0;        if (runContext == null)            type = RunContextType.CurrentThread;        else            type = runContext.value();        Delay delayAnno = method.getAnnotation(Delay.class);        if (delayAnno!=null)            delay = delayAnno.value();        switch (type){            case CurrentThread:                invoke_current_thread(method,object,delay,values);                break;            case CurrentLoop:                invoke_current_loop(method,object,delay,values);                break;            case NewThread:                invoke_new_thread(method,object,delay,values);                break;            case MainThread:                invoke_main_thread(method,object,delay,values);                break;            case MainLoop:                invoke_main_loop(method,object,delay,values);                break;            case Calculate:                invoke_calculate(method,object,delay,values);                break;            case IO:                invoke_io(method,object,delay,values);                break;            case NewHandlerThread:                invoke_new_handler_thread(method,object,delay,values);                break;            case Dynamic:                invoke_dynamic(method, object, values);                break;        }    }
可以看到如果不指定运行的线程的话默认就是CurrentThread即直接调用。
Invoke_Dynamic是为以后的变换方法体做准备的,因为注解的指定是编译时确定的,不是变量而是常量。
4.最后为了使每个目标方法通过我们的调度器Invoker调用,而不是直接被调用,OnObserver和OnPublisher必须被代理,否则用户就直接调用了。
public class ObserverProxy<T> implements OnObserver<T>,IObserverProxy<T>{    private Vector<OnObserver<T>> observers;    private Invoker invoker;    public ObserverProxy() {        observers = new Vector<OnObserver<T>>();        invoker = Invoker.getInstance();    }    @Override    public void onSuccess(T t) {        String methodName = "onSuccess";        for (OnObserver<T> observer:observers){            try {                Method method = observer.getClass().getMethod(methodName,Object.class);                invoker.invoke(method,observer,t);            } catch (NoSuchMethodException e) {                e.printStackTrace();            }        }    }    @Override    public void onError(Throwable throwable) {        String methodName = "onError";        Class type = Throwable.class;        for (OnObserver<T> observer:observers){            try {                Method method = observer.getClass().getMethod(methodName,type);                invoker.invoke(method,observer,throwable);            } catch (NoSuchMethodException e) {                e.printStackTrace();            }        }    }    @Override    public void onFinished() {        String methodName = "onFinished";        for (OnObserver<T> observer:observers){            try {                Method method = observer.getClass().getMethod(methodName);                invoker.invoke(method,observer,null);            } catch (NoSuchMethodException e) {                e.printStackTrace();            }        }    }    @Override    public void addObserver(OnObserver<T> observer) {        observers.add(observer);    }    @Override    public void rmObserver(OnObserver<T> observer) {        observers.remove(observer);    }    @Override    public void clear() {        observers.clear();    }    @Override    public Vector<OnObserver<T>> getObservers() {        return observers;    }}

public class OnPublisherProxy<T> implements OnPublisher<T>{    private OnPublisher<T> onPublisher;    private Invoker invoker;    public OnPublisherProxy(OnPublisher<T> onPublisher) {        this.onPublisher = onPublisher;    }    @Override    public void call(OnObserver<T> observer) {        String MethodName = "call";        Class parType = OnObserver.class;        if (invoker == null)            invoker = Invoker.getInstance();        try {            Method method = onPublisher.getClass().getMethod(MethodName,parType);            invoker.invoke(method,onPublisher, observer);        } catch (NoSuchMethodException e) {            e.printStackTrace();        }    }}
用以上两个代理类代理原Publisher中的observers和onpubliser
忘了注解的实体:
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface RunContext {    RunContextType value()default RunContextType.CurrentThread;}
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Delay {    int value()default 0;}


至此调度器部分就基本结束了。让我们使用一下试试吧。
Publisher.<String>getInstance()                 .create(new OnPublisher<String>() {                     @Delay(3*1000)                     @RunContext(RunContextType.IO)                     @Override                     public void call(OnObserver<String> observer) {                         String res = null;                         res = httpmodel.dohttp();                         if (res!=null)                             observer.onSuccess(res);                         else                             observer.onError(new Throwable("error"));                     }                 })                 .bind(new OnObserver<String>() {                     @RunContext(RunContextType.MainThread)                     @Override                     public void onSuccess(String s) {                         resTextView.setText(s);                     }                     @RunContext(RunContextType.MainThread)                     @Override                     public void onError(Throwable throwable) {                         Toast.makeText(MainActivity.this,throwable.getMessage(),Toast.LENGTH_LONG).show();                     }                     @Override                     public void onFinished() {                     }                 })                 .post();

在IO线程中发布了从网络回去一段字符串,在UI线程中订阅更新UI,是不是看着很清爽?如果你是用的是AS的话,结合lambda表达式看的更清爽。完全没有原来
Handler的困扰。
预告:第三集是变换,即Rxjava中的操作符

1 0
原创粉丝点击