Runnable概述

Runnable接口可声明一连串的事务,常用于多线程处理。但是实现Runnable接口并不意味着开启了一个新线程,只是定义了接下来要做的事情,至于说这些事情要在主线程处理,还是在分线程处理,那得看我们在哪里运行Runnable实例。如果在Handler或者View中启动Runnable,那么Runnable事务便运行于UI线程;如果在Thread中启动Runnable,那么Runnable事务便运行于非UI线程。

实现Runnable接口只需重写run函数,该函数内部放的就是需要Runnable处理的事务。run方法无需显式调用,在启动Runnable实例时便会调用对象的run方法。

实现Runnable接口相对于继承Thread类来说,有以下好处: 
1、Runnable接口实质是共享代码,类似于函数调用,但又比函数调用灵活,因为Runnable可选择实际调用的时机,而不必像函数调用那样还得等待调用结束;
2、可以避免Java单继承方式的局限。如果一个新类继承了Thread类,就不能再继承别的类。但是Runnable只是接口,所以新类可以继承别的类,同时实现Runnable接口。

启动Runnable

一、采用Handler类的post方法
Handler常用的post方法有下面几种:
post : 立即启动Runnable
postDelayed : 延迟指定时间间隔后启动Runnable
postAtTime : 在指定时间启动Runnable
removeCallbacks : 回收/移除指定的Runnable

二、使用View类的post方法
View类也提供了post和postDelayed两个方法,控件或视图可以直接调用自身的post方法,无需另外声明Handler对象。查看View的post源码,会发现其内部就是调用自身Handler实例的post方法。

三、利用Thread类构造Runnable的新线程
Thread方式启动Runnable,也只需两个步骤,第一步使用Runnable对象构造一个Thread实例,第二步启动这个Thread实例,代码如下:

         Thread runTread = new Thread(mRun);runTread.start();

完整的示例代码如下:

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;public class MainActivity extends Activity implements OnClickListener {private Handler mHandler = new Handler();private TextView tv_runnable;private int mCount = 0;private int mOffset = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button btn_handler = (Button) findViewById(R.id.btn_handler);Button btn_view = (Button) findViewById(R.id.btn_view);Button btn_thread = (Button) findViewById(R.id.btn_thread);btn_handler.setOnClickListener(this);btn_view.setOnClickListener(this);btn_thread.setOnClickListener(this);tv_runnable = (TextView) findViewById(R.id.tv_runnable);}private Runnable mRun = new Runnable() {@Overridepublic void run() {if (mCount < 20) {tv_runnable.scrollBy(-mOffset, -mOffset);//Thread方式启动Runnable时不能调用invalidate方法//tv_runnable.invalidate();tv_runnable.postInvalidate();mHandler.postDelayed(this, 200);mCount++;}}};@Overridepublic void onClick(View v) {mCount = 0;if (v.getId() == R.id.btn_handler) {mOffset = 10;mHandler.postDelayed(mRun, 500);} else if (v.getId() == R.id.btn_view) {mOffset = 10;tv_runnable.postDelayed(mRun, 500);} else if (v.getId() == R.id.btn_thread) {mOffset = -10;Thread runTread = new Thread(mRun);runTread.start();}}}

Runnable的适用场景

实际开发中,Runnable一般会延迟一段时间后启动,这个特性可用于四个方面:
1、有些事情需要在Activity页面显示出来后才能做,比如广播接收器一般在onStart或者onResume中注册,所以onCreate方法中若想发送广播后就能接收广播,那得延迟一点时间。
2、页面上有些事务不能让用户久等,所以如果事务本身无法设置超时时间的话,就得使用Runnable在事务超时后强行结束该事务。
3、在Runnable内部postDelayed自身,并持续post若干周期刷新视图,可实现动画效果。该功能的例子见《 Android开发笔记(十四)圆弧进度动画》
4、有些监听器如果没有得到合适的结果,就要持续监听,直到出现合适的结果为止。该功能的例子见《 Android开发笔记(四十六)手机相关事件》

视图刷新中的post方法

下列方法用于刷新View自身视图:
invalidate : 在UI线程中刷新视图
postInvalidate : 在非UI线程中刷新视图
postInvalidateDelayed : 在非UI线程中延迟若干时间后刷新视图

为避免误解,这里对invalidate和postInvalidate的区别做进一步的说明:
1、invalidate只能在UI线程中调用,所以如果在Thread方式中调用invalidate就会抛出异常;postInvalidate可在Thread方式中调用,但并不是不能在UI线程中调用,实际上postInvalidate既可在UI线程中调用,也可在非UI线程中调用;
2、invalidate只能立即刷新视图,而post方式还有postInvalidateDelayed方法可以延迟一段时间,查看postInvalidate的源码,会发现postInvalidate其实就是调用延迟0秒的postInvalidateDelayed;
从上面可以看出,invalidate的适用面较窄,而postInvalidate适用面较广,当然还是postInvalidateDelayed用起来更灵活些。

点此查看Android开发笔记的完整目录

Android开发笔记(四十七)Runnable接口实现多线程相关推荐

  1. Android开发笔记(十七)GIF动画的实现GifAnimation

    GIF在Windows上是常见的图片格式,主要用来播放短小的动画.但在手机上由于系统资源紧张,所以Android并没有直接支持GIF格式,如果在ImageView中放入一张gif文件,你会发现显示出来 ...

  2. Android开发笔记之:Handler Runnable与Thread的区别详解

    From:http://www.jb51.net/article/37465.htm 本篇文章是对在Android中Handler Runnable与Thread的区别进行了详细的分析介绍,需要的朋友 ...

  3. 【Visual C++】游戏开发笔记四十七 浅墨DirectX教程十五 翱翔于三维世界 摄像机的实现

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 本系列文章由zhm ...

  4. 【Visual C++】游戏开发笔记四十七 浅墨DirectX教程十五 翱翔于三维世界:摄像机的实现...

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:http://blog.csdn.net/zhmxy555/article/details/8657656 作者:毛星云(浅墨) ...

  5. 【Visual C++】游戏开发笔记四十七 浅墨DirectX教程十五 翱翔于三维世界:摄像机的实现

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处.   文章链接: http://blog.csdn.net/zhmxy555/article/details/8657656 作者:毛星云( ...

  6. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  7. Android开发笔记(序)

    本开发笔记,借鉴与其他开发者整理的文章范例与心得体会.在这里作为开发过程中的一个总结与笔记式记录. 如有侵犯作者权益,请及时联系告知删除.俗话说:集百家成一言,去粕成金. ************** ...

  8. Android开发笔记(序)写在前面的目录大全

    转自  湖前琴亭 的博客https://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面 ...

  9. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

最新文章

  1. javascript高级程序设计笔记
  2. Kubuntu 9.10设置支持文件分级的方法
  3. endnote咋手动输入文献_endnote如何导入参考文献?如何手动导入EndNote
  4. 1712: 最大乘积(贪心/dfs)
  5. 关于Java中try-catch-finally-return语句的思考
  6. 链地址处理哈希冲突方法
  7. qcustomplot删除一条曲线_被“谭卓”旗袍造型给惊艳,波波头搭配一条酒红色旗袍,华丽高贵...
  8. navicat 将自增长字段重置(重新从1开始)的方法
  9. mysql mvcc gap lock_为什么说 MVCC 和 Gap Lock 解决了 MySQL 的幻读问题
  10. PyTorch实战福利从入门到精通之一——PyTorch框架安装
  11. rhel6+apache2.4+mysql5.7+php5.6部署LAMP架构
  12. php mysql修改表单数据_表单修改数据
  13. GraphX 基础一
  14. 腾讯 QQ for Linux 的安装及 tar.gz版本QQ 建立快捷方式
  15. 在边缘试探的滴滴顺风车 凭什么在2019年再上线?
  16. 聊天类APP功能测试总结
  17. 真三国无双3 己方士气提升
  18. 工厂如何提升生产环境管理水平?动环监控排第几
  19. Spark之wordCount合集
  20. 片段@厦门鼓浪屿,琴岛猫缘

热门文章

  1. 梯度为什么是函数增加最快的方向
  2. Greenplum 行存、列存,堆表、AO表的原理和选择
  3. python文件转换成jar包_Python一键转Jar包,Java调用Python新姿势!
  4. python中监控错误的语句_Python学习_07_错误、异常
  5. python删除长目录_python中删除目录名两端
  6. 计算机代码如何求三角形面积,简单的程序来计算三角形的面积
  7. 利用宝塔部署若依前后分离项目(详细教程)
  8. 美观的导航菜单 -- JQuery实现,支持横向, 竖向
  9. Linux下VNCSERVER的使用介绍
  10. 计算机网络通信选择题,计算机网络教(学)案通信技术选择题试题题库完整