关于Android的异步操作,我在文章《Android开发实践:线程与异步任务》中介绍了两种方法,一种是采用线程,另一种是采用AsyncTask,今天再深入探讨下另一种模型:命令式的异步任务管理。

一般而言,单一的异步操作,比如从指定的网址下载一个图片采用线程或者AsyncTask是很方便的;如果异步任务是需要循环处理,比如定时更新某个UI控件,那么,可以通过定时器或者线程+Sleep循环来实现。那么,还有这么一种需求,需要你通过命令来与你的异步线程进行交互,比如你要远程操作一台设备,可以执行:打开、获取参数、设置参数、发送命令、关闭等等,这样的需求下,你的确可以通过对每一个命令开启一个线程的方式来实现,然而还有更好地方法么?

针对这种需求,我们来一起设计了一个基于命令模式的异步任务线程,在该线程启动后,在你没有发送命令的情况下,休眠等待;你可以连续向该线程发送一系列的命令,该线程会唤醒,并依次执行你所发送的命令,并在需要的情况下回调通知命令的发生者。

1. 命令模式

根据需求,我们可以知道,这样的设计采用命令模式最好不过了,所谓命令模式,就是将一个请求或者操作封装到一个对象中,命令的管理者不需要知道每个命令的具体参数和执行方法,只需要通过队列将命令对象缓冲起来,并在需要的时候依次调用命令对象的执行接口即可。

在这里,我们的任务就可以抽象为命令模式中的“命令”,首先设计任务的接口:

public interface Tasker {

public void execute();

}

2. 任务的定义

根据命令模式的定义,每个任务都可以设计为一个类,实现该Tasker的接口,作为示例,我实现了Tasker接口的对象的两个简单的任务类:

(1)“空任务”类,啥都不做

public class EmptyTasker implements Tasker {

@Override

public void execute() {

}

}

(2)“延时任务”类,负责在指定的延时之后执行任务

public class DelayTasker implements Tasker {

private final long mDelayTime;

private final TimeArrivedListener mListener;

//回调函数,通知外界延时时间到

public interface TimeArrivedListener {

public void onDelayTimeArrived();

}

//通过构造函数传递所需的参数

public DelayTasker( long delayTime, TimeArrivedListener listener){

mDelayTime = delayTime;

mListener = listener;

}

@Override

public void execute() {

try {

Thread.sleep(mDelayTime);

mListener.onDelayTimeArrived();

}

catch (InterruptedException e) {

e.printStackTrace();

}

}

}

3. 任务管理者

任务管理者负责管理任务队列,实现任务的执行,同时向使用者提供可访问的接口,主要包括如下实现:

(1) 任务执行线程

负责从任务队列取任务对象,并且调用任务的执行函数执行任务代码。

(2) 任务队列

以先进先出的形式管理任务队列,并且要注意多线程的读写安全。

(3) 调用接口

一般包括:初始化(开启任务线程)、逆初始化(关闭任务线程)、添加命令

我设计的任务管理者代码如下,你可以根据自己的需求添加/修改/删除接口或者实现细节。

public class TaskExecutor {

//控制线程执行/退出的标志变量

private volatile boolean mIsRunning = true;

//锁和条件变量

private Lock mLock = new ReentrantLock();

private Condition mCondition = mLock.newCondition();

//任务列表

private Queue mTaskerQueue = new LinkedList();

//初始化函数,开启任务等待线程

public void initilize() {

new Thread(new WorkRunnable()).start();

}

//销毁函数,关闭任务等待线程

public void destroy() {

//线程退出命令

mIsRunning = false;

//添加一个任务,唤醒mCondition.await

addTasker(new EmptyTasker());

}

//添加一个新任务

public void addTasker( Tasker tasker ) {

mLock.lock();

mTaskerQueue.add(tasker);

mCondition.signal();

mLock.unlock();

}

//获取下一个任务,如果任务列表为空,则阻塞

private Tasker getNextTasker() {

mLock.lock();

try {

//如果任务队列为空,则阻塞等待

while( mTaskerQueue.isEmpty() ) {

mCondition.await();

}

//返回队列首任务,并从队列删除掉

return mTaskerQueue.poll();

}

catch (InterruptedException e) {

e.printStackTrace();

}

finally {

mLock.unlock();

}

return null;

}

//任务等待/执行线程

private class WorkRunnable implements Runnable {

@Override

public void run() {

while(mIsRunning) {

Tasker tasker = getNextTasker();

tasker.execute();

}

Log.d("TaskExecutor", "WorkRunnable run exit ! ");

}

}

}

4. 使用案例

这里,我简单地应用上述异步任务线程完成了一个app示例,该app只有一个Button,每点击一次就延时1s弹出一个Toast消息,当你连续点击Button的时候,就会从1往后不断加1,连续的显示。

该app的MainActivity代码如下:

public class MainActivity extends Activity implements TimeArrivedListener {

private TaskExecutor mTaskExecutor;

private int mClickTimes = 0;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTaskExecutor = new TaskExecutor();

mTaskExecutor.initilize();

}

@Override

protected void onDestroy() {

mTaskExecutor.destroy();

super.onDestroy();

}

public void onClickDelay(View v) {

//每点击一次按钮,则延时1s,弹出消息提示

mTaskExecutor.addTasker(new DelayTasker(1000, this));

}

@Override

public void onDelayTimeArrived() {

mClickTimes++;

this.runOnUiThread(new Runnable() {

@Override

public void run() {

Toast.makeText(MainActivity.this,"This is the " + mClickTimes + " times click" , Toast.LENGTH_SHORT).show();

}

});

}

}

基于命令模式的异步任务线程就探讨到这里了,在你的Android工程中可以很容易地移植TaskExecutor类,本工程的项目代码见博文后面的附件,有任何疑问欢迎留言或者来信lujun.hust@gmail.com交流,一起探讨和完善这种异步任务线程。

android并发命令,Android开发实践:基于命令模式的异步任务线程相关推荐

  1. android电视盒子设备名字,Android电视TV盒子开发——常用ADB命令-Go语言中文社区...

    目前智能电视(TV).盒子(机顶盒)基本都是Android系统,所以开发盒子app的重任自然就会落到我们这些苦逼Android程序员身上. PS:目前盒子的Android版本绝大部分还都是在6.0以下 ...

  2. Android电视TV盒子开发——常用ADB命令

    目前智能电视(TV).盒子(机顶盒)基本都是Android系统,所以开发盒子app的重任自然就会落到我们这些苦逼Android程序员身上. PS:目前盒子的Android版本绝大部分还都是在6.0以下 ...

  3. 基于android的移动应用开发PPT,基于Android的移动应用开发课件.ppt

    基于Android的移动应用开发课件.ppt * 界面事件 触摸事件 当手指接触到触摸屏.在触摸屏上移动或离开触摸屏时,分别会引发ACTION_DOWN.ACTION_UP和ACTION_MOVE触摸 ...

  4. 基于android的个人理财软件 android stu_Android聊天软件开发(基于网易云IM即时通讯)——注册账号(二)...

    OKhttp封装 IRequest package heath.com.chat.OKhttp;import java.util.Map;public interface IRequest {publ ...

  5. Android进阶——组件化开发实践(一)

    一.组件化的意义 随着Android 项目代码和结构逐渐复杂,维护成本会指数型上升,通常我们会利用Android Studio自带的Module去拆分项目代码.但这种拆分显然需要基于一定逻辑和结构,目 ...

  6. Unity3D与AvosCloud网游开发实践 - 单线程U3D中的异步通讯处理

    Unity3D被设计为单线程的结构,即在主线程之外绝大多数API都是无法使用的,而AvosCloud所有数据通讯都是异步的,这样就产生了一些问题. 举例来说,角色获得了足够的升级经验,于是向服务器发送 ...

  7. android 多线程 崩溃,Android异常崩溃捕获

    Android系统碎片化造成应用程序崩溃严重,在模拟器上运行良好的程序安装到某款手机上说不定就会出现崩溃的现象.而且,往往都是程序发布之后在用户端出现了崩溃现象.所以在程序发布出去之后,如果出现了崩溃 ...

  8. Android开发实践:常用NDK命令行参数

    Android提供了NDK工具,用来编译native代码(c/c++),该工具配置好了相关的交叉编译环境和工具链,只需要你简单地编写几个.mk文件即可将你的c/c++代码编译为Android的java ...

  9. Android AR开发实践之四:基于Sceneform的ARcore开发实例

    Android AR开发实践之四:基于Sceneform的ARcore开发实例 一.设备配置 1.配置虚拟设备 2.配置真机 二.开发环境配置 1.首先添加sceneform的gradle插件到工程配 ...

最新文章

  1. gnome3.2 安装体验
  2. leetcode旋转数组 c语言,leetcode explore 初级算法第三题,旋转数组代码实现
  3. 关于Spring的笔试题(一)
  4. The Preliminary Contest for ICPC Asia Nanjing 2019 B. super_log (广义欧拉降幂)
  5. sprintf()、fprintf()的使用方法
  6. GDB调试之ptrace实现原理
  7. 个个都在比赚钱,有没比不赚钱的
  8. 局域网(网上邻居)共享问题全方位解决
  9. pageoffice在线编辑时向保存方法传递参数
  10. Python的伪造数据生成器:Faker
  11. 微信小程序支付V3(Java版)
  12. 利用一个竞态漏洞root三星s8的方法
  13. 极限中0除以常数_第六讲 极限的运算法则
  14. 因子模型:套利定价理论APT
  15. table行的折叠和展开
  16. 基于深度学习的几何模型表示 分析与合成
  17. Mathematica的基本量
  18. 双截龙java游戏下载_双截龙合集游戏
  19. My97DatePicker(WdatePicker)日期控件用法
  20. 【案例】下载站自动化 一个月发布3000+原创文章

热门文章

  1. 鸿蒙系统版本QQ,qq极速版鸿蒙版2020最新下载-QQ极速版 鸿蒙版v4.0.2-PC6鸿蒙网
  2. 【TOMVIP邮箱618抢购活动】,注册即送靓号,更多惊喜福利!
  3. [附源码]java毕业设计宠物狗领养网站
  4. 自定义View——双色球彩票选号界面,模仿网易彩票
  5. 关于参与新星计划的那一刻
  6. python调用opencv处理视频_Python调用OpenCV读写视频
  7. 1.6 如何使用SES搭建SIG MESH开发环境
  8. 题目3:一段楼梯共n级台阶,规定每一步只能跨一级或两级或三级。要等上第n级台阶共有几种走法?
  9. [转]VS编译duilib项目时候的错误解决方法整理
  10. 什么是角色建模?3D角色建模简介