• 山西税务系统一次性“打包”12项业务 2019-10-13
  • 江干区结对帮扶西藏那曲教育玩转“一对一”“多对一” 2019-10-11
  • 6月15日一分钟阅尽天下军情 2019-10-11
  • 赌王四太家的豪宅曝光,网友:一点都不羡慕 ——凤凰网房产 2019-10-10
  • 郭碧婷曝杨幂怀孕趣事,杨幂实力学习台湾腔 2019-10-10
  • 川航成功备降获赞还需反思 提直降代倒逼OTA服务提升 2019-10-10
  • 旅游--北京频道--人民网 2019-09-19
  • 山东将推动各类保护区范围内煤矿有序退出 2019-09-19
  • 史上最大锦鲤!南京大二女生一次收到618个快递 2019-09-14
  • 俄罗斯球队为国争光,为普京争脸。揭幕战横扫沙特队,吸引世界眼球。一代伟人普京,是俄罗斯人民的福气,强国,强军、富民,是普京献词“地球盛宴”的真正荣耀时刻,俄国人 2019-09-14
  • 海军第27批护航编队结束对摩洛哥访问  2019-09-05
  • 【脱贫路上】衣比·衣明: 小庭院里巧增收 2019-09-05
  • 华媒:瑞士失业率创历史新低 技术型劳动力短缺 2019-09-04
  • 告别“电钻音”安静“不扰民” 九阳率先推出静音破壁机 2019-09-01
  • 《歌手》首发阵容6年来最尬?令我震惊的只有…… 2019-08-23
  • 六合图库财神 >Android相关

    Android异步、延迟和定时任务的简易用法

    2019-03-14 10:48 编辑: suiling 分类:Android相关 来源:蝴蝶之梦天使

    异步多线程

    延迟触发

    循环定时触发

    一、前言

    项目开发中一定会用到网络请求,文件读写,开启子线程进行耗时操作,延迟返回或关闭提示框,轮询接口获取处理结果,子线程发送内容到主线程更新界面等等。碰到这些问题或需求的时候,每位程序猿都会使用自己喜欢或习惯的用法来实现或界面问题。当然结果是功能完成了或问题修复了。但是代码风格的差异,使用时考虑不全,使用方法不是最优,等等多多少少存在一些瑕疵。例如:

    • 阿里的java编程规范不推荐显式使用Thread

    • 直接使用AsyncTask存在内存泄露或者weak用法导致空指针的问题

    • 使用Handler进行更新界面的复杂操作

    • 使用postDelayed()进行延迟操作不能在子线程中使用

    • 使用TimerTask进行轮询时复杂的更新页面

    • 综上,特别想在代码上统一用法,并且是简单又安全,而且性能最优。所以想到RxJava是不是可以来实现这个愿望。尝试和研究中记录的Demo,有使用错误或更好的方案,请多指教。

    二、 铺垫

    1. RxJava集成

        项目中先集成RxJava库

    api 'io.reactivex.rxjava2:rxandroid:2.1.0'
    api 'io.reactivex.rxjava2:rxjava:2.2.5'
    api 'com.squareup.retrofit2:retrofit:2.5.0'
    api 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
    api 'com.squareup.retrofit2:converter-gson:2.5.0'

    关于RxJava的方法介绍或基础使用,请参考RxJava2在Android中的使用。

    2. RxJava多线程

        使用RxJava进行多线程操作的原理、用法及其他,请参考在 Andoid 中如何使用 RxJava 2 进行多线程编程?.

    3. Scheduler

        针对多线程的操作,Schedulers的参数了解,请参考我所理解的RxJava——上手其实很简单(三);

    三、异步

    最直接的用法就是new Thread()创建一个子线程,然后用EventMessage或Handler发送Message来更新页面。更好一点的方法是ExecutorService创建线程池,统一管理线程并且复用线程以及控制线程的总数,但是需要再花点时间维护和优化。但是不建议为每一个Activity或fragment创建一个线程池,从性能和线程复用率上没有必要性。

    private void testCreate() {
            Observable.create(new ObservableOnSubscribe() {
                @Override
                public void subscribe(ObservableEmitter emitter) throws Exception {
                    Log.e("wyn", "ObservableEmitter");
                    
                    Log.e("wyn", "ObservableEmitter thread is " + Thread.currentThread().getName());
                    
                    
                    long a = 1;
                    for (int i = 0; i < 1000000000; i++) {
                        a = a + (a + 1);
                    }
                    
                    Log.e("wyn", "a is " + a);
                    emitter.onNext("wang" + a);
                    emitter.onNext("yinan");
                    
                    emitter.onComplete();
                }
            }).subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(this.observerString);
        }

    打印的结果

    2019-01-18 11:03:08.326 27120-27120/? E/wyn: onSubscribe
    2019-01-18 11:03:08.326 27120-27120/? E/wyn: onSubscribe thread is main
    2019-01-18 11:03:08.328 27120-27138/? E/wyn: ObservableEmitter
    2019-01-18 11:03:08.328 27120-27138/? E/wyn: ObservableEmitter thread is RxCachedThreadScheduler-1
    2019-01-18 11:03:13.226 27120-27138/com.example.RxThread E/wyn: a is -1
    2019-01-18 11:03:13.227 27120-27120/com.example.RxThread D/wyn: onNext is wang-1
    2019-01-18 11:03:13.227 27120-27120/com.example.RxThread E/wyn: onNext thread is main
    2019-01-18 11:03:13.229 27120-27120/com.example.RxThread D/wyn: onNext is yinan
    2019-01-18 11:03:13.229 27120-27120/com.example.RxThread E/wyn: onNext thread is main
    2019-01-18 11:03:13.229 27120-27120/com.example.RxThread E/wyn: onComplete
    2019-01-18 11:03:13.229 27120-27120/com.example.RxThread E/wyn: onComplete thread is main

    重点

    使用create方法简易的实现子线程操作(subscribeOn设置子线程类型),发送内容(onNext发送内容)到主线程(observeOn设置在主线程操作)更新界面。

    四、延迟

    最直接的方案就是postDelayed()触发一个延迟的操作。如果是在子线程进行postDelayed()操作,那么不能直接使用,会崩溃。

    private void testTimer() {
            Observable.timer(3, TimeUnit.SECONDS)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(this.observer);
        }

    输出:

    2019-01-18 11:31:11.820 28231-28231/com.example.RxThread E/wyn: onSubscribe
    2019-01-18 11:31:11.820 28231-28231/com.example.RxThread E/wyn: onSubscribe thread is main
    2019-01-18 11:31:14.832 28231-28231/com.example.RxThread D/wyn: onNext is 0
    2019-01-18 11:31:14.833 28231-28231/com.example.RxThread E/wyn: onNext thread is main
    2019-01-18 11:31:14.835 28231-28231/com.example.RxThread E/wyn: onComplete
    2019-01-18 11:31:14.835 28231-28231/com.example.RxThread E/wyn: onComplete thread is main

    Timer可以在子线程进行延迟操作,那么输出结果为:

    2019-01-18 11:33:14.018 28398-28419/? E/wyn: onSubscribe
    2019-01-18 11:33:14.019 28398-28419/? E/wyn: onSubscribe thread is Thread-2
    2019-01-18 11:33:17.026 28398-28398/com.example.RxThread D/wyn: onNext is 0
    2019-01-18 11:33:17.027 28398-28398/com.example.RxThread E/wyn: onNext thread is main
    2019-01-18 11:33:17.029 28398-28398/com.example.RxThread E/wyn: onComplete
    2019-01-18 11:33:17.030 28398-28398/com.example.RxThread E/wyn: onComplete thread is main

    重点

    timer设置延迟的时间,然后在主线程更新界面。

    五、定时、轮询、循环

    一般轮询接口获取数据或倒计时显示内容,使用TimerTask来实现,然后采用Handler发送Message更新界面。

    private void testInterval() {
            Observable.interval(3, TimeUnit.SECONDS)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(this.observer);
        }

    输出结果:

    2019-01-18 11:41:42.108 29064-29064/? E/wyn: onSubscribe
    2019-01-18 11:41:42.108 29064-29064/? E/wyn: onSubscribe thread is main
    2019-01-18 11:41:45.115 29064-29064/com.example.RxThread D/wyn: onNext is 0
    2019-01-18 11:41:45.115 29064-29064/com.example.RxThread E/wyn: onNext thread is main
    2019-01-18 11:41:48.112 29064-29064/com.example.RxThread D/wyn: onNext is 1
    2019-01-18 11:41:48.112 29064-29064/com.example.RxThread E/wyn: onNext thread is main
    2019-01-18 11:41:51.113 29064-29064/com.example.RxThread D/wyn: onNext is 2
    2019-01-18 11:41:51.114 29064-29064/com.example.RxThread E/wyn: onNext thread is main
    2019-01-18 11:41:54.113 29064-29064/com.example.RxThread D/wyn: onNext is 3
    2019-01-18 11:41:54.114 29064-29064/com.example.RxThread E/wyn: onNext thread is main
    .......

    重点

    interval间隔指定的时间,在主线程执行操作。

    六、补充

    测试代码中使用到的observer和observerString,

    private Observer observer = new Observer() {
            Disposable disposable;
            
            @Override
            public void onSubscribe(Disposable d) {
                Log.e("wyn", "onSubscribe");
                
                Log.e("wyn", "onSubscribe thread is " + Thread.currentThread().getName());
                
                disposable = d;
            }
            
            @Override
            public void onNext(Long s) {
                Log.d("wyn", "onNext is " + s);
                
                Log.e("wyn", "onNext thread is " + Thread.currentThread().getName());
                
                tvContent.setText(s + "");
                
                if (s == 10) {
                    disposable.dispose();
                }
            }
            
            @Override
            public void onError(Throwable e) {
                Log.e("wyn", "onError");
                
                Log.e("wyn", "onError thread is " + Thread.currentThread().getName());
            }
            
            @Override
            public void onComplete() {
                Log.e("wyn", "onComplete");
                
                Log.e("wyn", "onComplete thread is " + Thread.currentThread().getName());
            }
        };
        
        private Observer observerString = new Observer() {
            Disposable disposable;
            
            @Override
            public void onSubscribe(Disposable d) {
                Log.e("wyn", "onSubscribe");
                
                Log.e("wyn", "onSubscribe thread is " + Thread.currentThread().getName());
                
                disposable = d;
            }
            
            @Override
            public void onNext(String s) {
                Log.d("wyn", "onNext is " + s);
                
                Log.e("wyn", "onNext thread is " + Thread.currentThread().getName());
                
                tvContent.setText(s);
            }
            
            @Override
            public void onError(Throwable e) {
                Log.e("wyn", "onError");
                
                Log.e("wyn", "onError thread is " + Thread.currentThread().getName());
            }
            
            @Override
            public void onComplete() {
                Log.e("wyn", "onComplete");
                
                Log.e("wyn", "onComplete thread is " + Thread.currentThread().getName());
            }
        };

    七、注意

    选择子线程操作的时候,如果有文件操作那么一定要用Schedulers.io()。不然建议使用Schedulers.computation().

    八、其他

    从友盟统计iOS和Android的崩溃来看,Android的空指针崩溃真的是多如牛毛啊。为啥不整一个nil类型,从系统级别上,进行全局的空指针的?;つ?!少一点崩溃,多一点快乐?。?!

    // END

    作者:蝴蝶之梦天使

    链接:https://www.jianshu.com/p/cee49d6d817f

    搜索CocoaChina微信公众号:CocoaChina
    微信扫一扫
    订阅每日移动开发及APP推广热点资讯
    公众号:
    CocoaChina
    我要投稿   收藏文章
    上一篇:2018年年底Android悲催的面试之路

    相关资讯

    我来说两句
    发表评论
    您还没有登录!请登录注册
    所有评论(0

    综合评论

    相关帖子

    sina weixin mail 回到顶部
  • 山西税务系统一次性“打包”12项业务 2019-10-13
  • 江干区结对帮扶西藏那曲教育玩转“一对一”“多对一” 2019-10-11
  • 6月15日一分钟阅尽天下军情 2019-10-11
  • 赌王四太家的豪宅曝光,网友:一点都不羡慕 ——凤凰网房产 2019-10-10
  • 郭碧婷曝杨幂怀孕趣事,杨幂实力学习台湾腔 2019-10-10
  • 川航成功备降获赞还需反思 提直降代倒逼OTA服务提升 2019-10-10
  • 旅游--北京频道--人民网 2019-09-19
  • 山东将推动各类保护区范围内煤矿有序退出 2019-09-19
  • 史上最大锦鲤!南京大二女生一次收到618个快递 2019-09-14
  • 俄罗斯球队为国争光,为普京争脸。揭幕战横扫沙特队,吸引世界眼球。一代伟人普京,是俄罗斯人民的福气,强国,强军、富民,是普京献词“地球盛宴”的真正荣耀时刻,俄国人 2019-09-14
  • 海军第27批护航编队结束对摩洛哥访问  2019-09-05
  • 【脱贫路上】衣比·衣明: 小庭院里巧增收 2019-09-05
  • 华媒:瑞士失业率创历史新低 技术型劳动力短缺 2019-09-04
  • 告别“电钻音”安静“不扰民” 九阳率先推出静音破壁机 2019-09-01
  • 《歌手》首发阵容6年来最尬?令我震惊的只有…… 2019-08-23
  • 彩无敌时时彩计划软件 11选5任选1精准计划在线 分分彩龙虎和最聪明的玩法 西红柿计划app下载 求猫咪看片app 21点的攻略和必胜法 全天时时彩最准计划 幸运28大小单双怎么买 大乐透全国都能兑奖吗 赌三公赢钱有什么规律