美文网首页
RxJava实现Android MVP

RxJava实现Android MVP

作者: 浮云骑士_ | 来源:发表于2017-03-08 16:46 被阅读0次

    前言:MVP是什么我就不讲了,如果需要的可以去百度查查资料。

    RxJava是观察者模式的一种实现,观察者为Consumer或者Subscriber 被观察者为Flowable

    我们大致理一理,实现一个Present需要什么内容:

    • 1.基本的,Present要得到Activity的实例对象,它们是一对一的关系。

    • 2.首先,Present肯定是被观察者,他要处理完事件后返回结果给观察它的人。所以他要实现Flowable中具体的方法。

    • 3.他要有接受事物处理的对象,也就是函数的参数,然后根据参数来进行处理和返回结果

    • 4.他要有返回结果的能力,所以需要接受观察者的监听容器(Consumer,Subscriber),这也是需要写在函数之中的。

    • 5.他要有处理多线程并能返回到主线程的能力,因为我调用了网络请求后不可能将子线程回到主线程的操作交由View处理。

    • 6.他要避免内存泄漏,因为Present很多情况下需要用到多线程,如果持有Activity的实例,那么就会造成Activity释放的不及时。

    这就是我整理出来的对Present的4点要求,下面我们一一实现。

    以下主要涉及三个类,MainActivity(视图类),BasePresent(Present的基类),MainActivityPresent(MainActivity对应的Present实现类)

    ** 公共属性 **

    我觉得把一些能够一起实现的放在基类里面,然后根据各有的特色进行继承,这样优化了代码的可读性和代码量
    这里的公共属性我觉得有两个,一是回到主线程的能力,二是处理内存泄漏,不多说,先帖代码

    public class BasePresent {
    
        private WeakReference<Context> mContext ;
    
        protected BasePresent(Context context){
            mContext = new WeakReference<Context>(context);
        }
    
    
        protected Context getContext(){
            return mContext.get();
        }
    
        protected void runOnUIThread(Runnable runnable){
            //判断Context的合理
            if(runnable==null || mContext.get() == null || !(mContext.get() instanceof Activity)){
                return ;
            }
            ((Activity)mContext.get()).runOnUiThread(runnable);
    
        }
    }
    

    可以看到,我们通过WeakRefrence实现了对Activity的弱应用,而且通过给子类暴露的getContext方法,一是解决了内存泄漏的问题,二是对子类感受不到处理内存泄漏过程的存在。我们用构造方法来表明,我的Present必须持有Activity对象。

    ** View **

    对于View来说,我只需要显示界面和调用Present,所以在View中必须实现对Present的初始化

    public class MainActivity extends BaseActivity {
    
        MainActivityPresent present ;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            present = new MainActivityPresent(this);
        }
    }
    

    ** 业务 **

    我现在有两个需求:

    • 1.MainActivity需要进行登录操作
    • 2.MainActivity需要下载图片并监听整个下载过程

    这两点有什么不同?

    确实有不同,第一个需求表示我传入一个值,返回给我一个结果就行了,但是第二个需求,需要我发送请求下载,然后下载的进度要实时的返回给我。

    ** RxJava2 实现 **

    先第一个需求,首先我们不写MainActivity,我们写Present

    首先我们需要有一个方法,

    MainActivityPresent.java:
    public void login(final Login login , final Consumer<String> consumer){
      ...
    }
    

    我们可以看到,我们登陆,需要接受View传给我的登陆信息,这里用Login,从而进行对数据的处理,处理完成后,需要返回结果给View,所以这里需要Consumer类,我们写一个完整的。 tip:使用final因为有用到线程读取数据

    public class MainActivityPresent extends BasePresent {
    
    
        public MainActivityPresent(Context context) {
            super(context);
        }
    
        public void login(final Login login , final Consumer<String> consumer){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //登陆代码.....
                    LogUtils.d("login");
                    //runOnUIThread
                    String result = "登陆成功";
                    final Flowable flowable = Flowable.just(result);
                    runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            flowable.subscribe(consumer);
                        }
                    });
    
                }
            }).start();
    }
    }
    

    重点有两句话

     final Flowable flowable = Flowable.just(result);
     flowable.subscribe(consumer);
    

    这里我们创建了一个Flowable对象,传入结果即将要返回的结果result ,在登陆完成后我们通过第二句代码来反馈给View。我们可以看到第二句话写在了runOnUIThread中,第二句话执行意味着回馈View

    接下来我们实现MainActivity的调用

    MainActivity.java:
    //对于只需要结果的数据,可以使用简单的Consumer
    present.login(new Login(), new Consumer<String>() {
        @Override
         public void accept(@NonNull String s) throws Exception {
            //登陆结果,s表示view需要present返回的类型
            LogUtils.d("accept");
             showTip(s);
         }
    });
    

    可以看到,我们调用时实现了Consumer类,并重载了accept方法,这个方法便是在登陆处理完成后Present回调的方法。


    下面我们实现第二个需求,第二个需求强调过程性,我们只能使用Subscriber来处理这个需求。

    也是,第一步,写Present

    方法

    MainActivityPresent.java:
    public void downloadImage(final String url ,final Subscriber<Integer> subscriber){}
    

    一样的,就不多说了,下面帖全部代码

    public class MainActivityPresent extends BasePresent {
    
    
        public MainActivityPresent(Context context) {
            super(context);
        }
    
        public void downloadImage(final String url ,final Subscriber<Integer> subscriber){
    
            Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
                @Override
                public void subscribe(final FlowableEmitter<Integer> e) throws Exception {
                    LogUtils.d("subscribe");
                    //下载代码
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                Thread.sleep(3000);
                                //传回更新数据
                                runOnUIThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        e.onNext(47);
                                    }
                                });
                                Thread.sleep(3000);
                                //传回下载完成数据
                                runOnUIThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        e.onComplete();
                                    }
                                });
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                    }).start();
                }
            }, BackpressureStrategy.BUFFER);
            flowable.subscribe(subscriber);
    
        }
    
    
    }
    

    我们可以看到过程很复杂,我们实现Flowable的方式也不同,这里最后也有一句,flowable.subscribe(subscriber); 这里注意的是,这句话执行并不意味着回馈消息,而是正式的注册监听,相当于关联起来。回馈消息重载的subscribe里面。

    我们可以看到在subscribe 我开启了子线程,过3秒后我回到主线程执行了e.onNext(47); 又过3秒我回到主线程执行了e.onComplete(); 这里你可能不清楚含义,我先大致说一下,第一句话表示下载过程时的实时更新反馈,第二句话表示完成下载后的反馈。

    好了 我们贴MainActivity的调用代码

    MainActivity.java:
        //对于需要过程的数据,需要用Subscriber,我们需要一个进度,这里选用Integer为进度消息
        present.downloadImage("", new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                LogUtils.d("onSubscribe");
                //开始请求
                showTip("start", Toast.LENGTH_SHORT);
                s.request(Long.MAX_VALUE);
            }
    
            @Override
            public void onNext(Integer integer) {
                LogUtils.d("onNext");
                //进度有更新
                showTip(integer+"", Toast.LENGTH_SHORT);
            }
    
            @Override
            public void onError(Throwable t) {
                LogUtils.d("onError");
                //下载出错
            }
    
            @Override
            public void onComplete() {
                LogUtils.d("onComplete");
                //下载完成
                showTip("complete");
            }
        });
    

    看到了什么?我们实现Subscriber类时,我们重载了onNext方法,onComplete方法,是不是和上面对应起来了? 是的,在MainActivityPresent中的 ”过3秒后我回到主线程执行了e.onNext(47); 又过3秒我回到主线程执行了e.onComplete();” 和这里对应,那里反馈的消息在这里被调用。

    😄,很难懂,自己慢慢理解

    贴个所有的代码

    public class BasePresent {
    
        private WeakReference<Context> mContext ;
    
        protected BasePresent(Context context){
            mContext = new WeakReference<Context>(context);
        }
    
    
        protected Context getContext(){
            return mContext.get();
        }
    
        protected void runOnUIThread(Runnable runnable){
            //判断Context的合理
            if(runnable==null || mContext.get() == null || !(mContext.get() instanceof Activity)){
                return ;
            }
            ((Activity)mContext.get()).runOnUiThread(runnable);
    
        }
    }
    
    
    public class MainActivityPresent extends BasePresent {
    
    
        public MainActivityPresent(Context context) {
            super(context);
        }
    
        public void login(final Login login , final Consumer<String> consumer){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //登陆代码.....
                    LogUtils.d("login");
                    //runOnUIThread
                    String result = "登陆成功";
                    final Flowable flowable = Flowable.just(result);
                    runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            flowable.subscribe(consumer);
                        }
                    });
    
                }
            }).start();
    
    
        }
    
        public void downloadImage(final String url ,final Subscriber<Integer> subscriber){
    
            Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
                @Override
                public void subscribe(final FlowableEmitter<Integer> e) throws Exception {
                    LogUtils.d("subscribe");
                    //下载代码
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                Thread.sleep(3000);
                                //传回更新数据
                                runOnUIThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        e.onNext(47);
                                    }
                                });
                                Thread.sleep(3000);
                                //传回下载完成数据
                                runOnUIThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        e.onComplete();
                                    }
                                });
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                    }).start();
                }
            }, BackpressureStrategy.BUFFER);
            flowable.subscribe(subscriber);
    
        }
    
    
    }
    
    public class MainActivity extends BaseActivity {
    
        MainActivityPresent present ;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            present = new MainActivityPresent(this);
    
            //对于只需要结果的数据,可以使用简单的Consumer
            present.login(new Login(), new Consumer<String>() {
                @Override
                public void accept(@NonNull String s) throws Exception {
                    //登陆结果,s表示view需要present返回的类型
                    LogUtils.d("accept");
                    //showTip(s);
                }
            });
    
            //对于需要过程的数据,需要用Subscriber,我们需要一个进度,这里选用Integer为进度消息
            present.downloadImage("", new Subscriber<Integer>() {
                @Override
                public void onSubscribe(Subscription s) {
                        LogUtils.d("onSubscribe");
                    //开始请求
                    showTip("start", Toast.LENGTH_SHORT);
                    s.request(Long.MAX_VALUE);
                }
    
                @Override
                public void onNext(Integer integer) {
                    LogUtils.d("onNext");
                    //进度有更新
                    showTip(integer+"", Toast.LENGTH_SHORT);
                }
    
                @Override
                public void onError(Throwable t) {
                    LogUtils.d("onError");
                    //下载出错
                }
    
                @Override
                public void onComplete() {
                    LogUtils.d("onComplete");
                    //下载完成
                    showTip("complete");
                }
            });
        }
    }
    

    相关文章

      网友评论

          本文标题:RxJava实现Android MVP

          本文链接:https://www.haomeiwen.com/subject/mlibgttx.html