AG亚游集团 >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

作者:蝴蝶之梦天使

链接:/www0686jianshu0686com/p/cee49d6d817f

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

相关资讯

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

综合评论

相关帖子

sina weixin mail 回到顶部
加拿大重大交通事故致14人死亡 暂无中国公民伤亡 刘晓彤承认女排打得较乱 整场节奏都被韩国掌握 穆里尼奥聊皇马卖C罗:皇马高于任何球员 他把相恋多年女友嫁给别人做老婆 结果被判刑 西媒分析托雷斯3大下家 西蒙尼表态不强留他 俄“花滑女神”生活简朴 日媒赞叹品质比金牌珍贵 1岁女童死亡全身30余处青紫 其父母均被判虐待罪 国台办谈“台独”“港独”同盟:沆瀣一气不得人心 押金、停车、盈利 共享汽车绕不过去的三道坎 美中期选举100天倒计时 希拉里或正策划卷土重来 “结构牛”行情可期? 放水暖风拂面大宗商品起锚 美加墨就修订北美自由贸易协定展开新一轮谈判
FIA严禁引擎吹气尾翼 雷诺狡猾设计合法但被警告 政府如何落实文化遗产保护责任?文化部长回应 新京报:建设西湖大学 追求的不是新增一所大学 马德里赛波特罗遭NO.95逆转 两位新星制造冷门 韩美首脑第15次通话:力促朝美会谈成功举行 欧盟穿梭外交意在把握经贸博弈先机 上市银行三季报7宗“最”:建行民生资产规模增长最多 新京报评店员卷款逃跑顾客无一逃单:自律将成习惯 霍金传奇:成名黑洞研究 告诉人类“时间有开端” 台学者:大陆不“让利”了 新路线制衡“天然独” 澳大利亚科学家赴瑞士安乐死 最后步骤由自己完成 郑州市长杯上演巅峰对决 胡葆森给青少年开球
韩国政府掏钱给共享单车配头盔 一周被偷走218个 贾跃亭的2017:连一片羽毛都不愿失去的他失去全世界 白边19板热火盘踞前八 格里芬31分活塞仍失利 改革后国务院8个部门领导班子副职中配党外干部 颜射哈登+摇头抖肩! 单节18分日天男回来了 下游回暖刺激镍价突破上行 集邦咨询:中国智能手机品牌全球市占率或扩大至54% 商场关着海豹环境恶劣?工作人员:排泄导致水浑浊 张艺谋:中国有足够文化自信 无需在8分钟表达太多 两万元投资 三缺一棋牌游戏平台 投资两万的小型加工厂 适合男生十大行业 AG亚游集团