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

前言:上一篇架构了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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值