前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(四十七)Runnable接口实现多线程

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

作者头像
aqi00
发布2019-01-18 11:12:30
2.1K0
发布2019-01-18 11:12:30
举报
文章被收录于专栏:老欧说安卓

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实例,代码如下:

代码语言:javascript
复制
			Thread runTread = new Thread(mRun);
			runTread.start();

完整的示例代码如下:

代码语言:javascript
复制
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;

	@Override
	protected 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() {
		@Override
		public void run() {
			if (mCount < 20) {
				tv_runnable.scrollBy(-mOffset, -mOffset);
				//Thread方式启动Runnable时不能调用invalidate方法
				//tv_runnable.invalidate();
				tv_runnable.postInvalidate();
				mHandler.postDelayed(this, 200);
				mCount++;
			}
		}
	};

	@Override
	public 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开发笔记的完整目录

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016年01月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Runnable概述
  • 启动Runnable
  • Runnable的适用场景
  • 视图刷新中的post方法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档