在平时的android开发工作中,我们常常须要运行耗时操作,有时为了用户体验还须要显示个等待框,我之前的做法都是开一个线程,然后用handler发消息进行显示和关闭等待框以及相关的ui操作。假设任务比較多的话,频繁的new Thread会让代码看上去比較混乱,并且还不好管理,针对这样的情况我写了tractor。

tractor基本的作用有:

1. 代码变得整洁。不用在到处new Thread和new Handler。

2. 能够监控任务的运行情况,能够随时取消一个或多个任务;

3. 封装了okhttp。支持大文件上传,多线程断点下载。get,post以及其它的网络请求

效果图

使用说明

类图

结构事实上非常easy。没有多少东西。

普通任务

//当LoadListenerImpl构造函数传入context,则显示progressdialog
doNormalTask(new LoadListenerImpl(this) {
@Override
public void onStart(Object result) {
super.onStart(result);
setMessage("任务開始运行");
} @Override
public void onSuccess(Object result) {
super.onSuccess(result);
String response = (String) result;
setMessage("任务结束");
} @Override
public void onFail(Object result) {
super.onFail(result);
String response = (String) result;
setMessage(response);
} @Override
public void onLoading(Object result) {
super.onLoading(result);
//以后不用写handler了,这样就能够处理了
int response = (int) result;
switch (response) {
case 1:
setMessage("正在运行 response=" + response);
break;
case 2:
setMessage("正在运行 response=" + response);
break;
case 3:
setMessage("正在运行 response=" + response);
break;
default:
break;
}
} @Override
public void onCancel(Object result) {
super.onCancel(result);
setMessage("任务被取消了");
} @Override
public void onCancelClick() {
super.onCancelClick();
TaskPool.getInstance().cancelTask(MainActivity.this);
}
}, this);

在上面的代码块中,LoadListenerImpl是LoadListener的实现类,用于监听任务载入的整个过程,使用LoadListenerImpl而不是LoadListener的优点有两点:

1.能够不实现全部的方法,仅仅要依据自己的须要来实现对应的方法即可了;‘

2.LoadListenerImpl中能够管理ProgressDialog。ProgressDialog能够用tractor中自带的,也能够自定义。

LoadListenerImpl 部分源代码:

public class LoadListenerImpl implements LoadListener {
private WeakReference<Context> context;
private ProgressDialog mProgressDialog;
private String mMessage = "载入中...";
private long mDismissTime = 500; /**
* 不显示progressdialog
*/
public LoadListenerImpl() {
} /**
* 显示progressdialog。其上显示的文字是默认的
* @param context
*/
public LoadListenerImpl(Context context) {
init(context, null);
} /**
* 显示progressdialog,其上显示的文字是message
* @param context
* @param message
*/
public LoadListenerImpl(Context context, String message) {
init(context, message);
}
/**
* 设置自定义的progressdialog,假设不设置则使用tractor自带的
* @param progressDialog
*/
public void setProgressDialog(ProgressDialog progressDialog) {
mProgressDialog = progressDialog;
}
......
}

当然了,你也能够自己实现LoadListener。毕竟是面向接口编程。

doNarmalTask方法的详细实现

 /**
* 发起个普通的任务
*
* @param listener
* @param tag
*/
public void doNormalTask(LoadListener listener, Object tag) {
TaskPool.getInstance().execute(new Task(tag, listener) {
@Override
public void onRun() {
SystemClock.sleep(500);
notifyLoading(1);
SystemClock.sleep(500);
notifyLoading(2);
SystemClock.sleep(500);
notifyLoading(3);
SystemClock.sleep(500);
Random random = new Random();
//任务是模拟的,所以随机下
if (random.nextBoolean()) {
//notifySuccess(null);
} else {
notifyFail("糟糕,任务失败了");
}
} @Override
public void cancelTask() { }
});
}

TaskPool.getInstance().execute()方法终于是把task交由线程池来运行。TaskPool仅仅负责加入和取消任务。接下来说Task,在上面的类图中有说明,Task是实现了Runnable接口,并重写run(),所以线程池能够运行Task,我们看下run()方法是怎么实现的:

public abstract class Task implements Runnable {
......
@Override
public final void run() {
start();
onRun();
finish();
}
......
private void start() {
notifyStart(null);
......
}
/**
* 实现这种方法来运行详细的任务
*/
public abstract void onRun();
private void finish() {
if (isRunning()) {
// 默认载入成功
mStatus = Status.SUCCESS;
notifySuccess(null);
}
clear();
}

run()中分别运行了start(),onRun()和finish(),start()方法中调用了notifyStart(null),finish()中调用了notifySuccess(null),也就是说在開始的时候会通知ui线程任务開始,结束的时候默认通知ui线程任务结束。

onRun()是抽象方法,是给任务调用者来实现运行详细的任务的。在运行的过程中能够通过notifyLoading(result)来通知ui任务的进度。notifySuccess(result)和notifyFail(result)通知ui任务成功和失败,并把须要的数据result作为參数传给ui线程。

至于Task中的cancelTask()放到后面取消任务的时候再说。

超时任务

 doTimeoutTask(500, new LoadListenerImpl() {
@Override
public void onStart(Object result) {
super.onStart(result);
toast("超时任务開始运行");
} @Override
public void onSuccess(Object result) {
super.onSuccess(result);
toast("超时任务运行成功");
} @Override
public void onTimeout(Object result) {
super.onTimeout(result);
toast("任务超时");
}
}, this);
.......
public void doTimeoutTask(long timeout, LoadListener listener, Object tag) {
TaskPool.getInstance().execute(new Task(timeout, tag, listener) {
@Override
public void onRun() {
SystemClock.sleep(1000);
} @Override
public void cancelTask() { }
});
}

能够看到。超时任务相较于普通任务来说仅仅是Task构造函数多了个timeout參数。这个timeout參数的含义就是任务运行的时间限制。假设超过这个限制就回调onTimeout()方法。

取消任务

在平时的开发过程中,有时开了一个超耗时的操作,在耗时操作未返回的时候页面就被关闭了。当页面关闭以后耗时操作才有了返回,这时候须要操作控件的话就有可能会报null或者其它的一些异常,为了避免异常,我们通常须要进行一些页面是否处于激活状态的推断,但是这样总是非常麻烦的。tractor攻克了这个问题,能够调用取消任务的方法,就像这样:

//取消任务的方法,參数能够是任务的tag,也能够是task。假设是tag,则取消tag相关的全部任务。是task则取消指定的task。
//能够在onDestroy()中调用
TaskPool.getInstance().cancelTask(tag|task);

这样调用以后会调用notifyCancel(null),在ui上显示给用户任务已取消的效果,tractor有个特性:当任务有结果时(已经取消,超时,成功和失败),兴许的notifyXXX()就都不会通知到ui线程了,所以假设任务在运行取消任务代码以后,当任务有结果返回的时候。ui回调也不会被运行。那么上面说的那个问题也就不存在了,就省的自己去加推断了。

前面也有提到,取消任务的代码仅仅能在保证ui上有取消的效果,但是任务实际上还是在运行的。尽管用户看不到但是资源还是在损耗,所以还不行。

从类图中能看到Task有onRun()和cancelTask()两个抽象方法,onRun()是运行详细任务的,cancelTask()则是运行详细的取消任务的操作。他是在非ui线程中运行的。详细怎么停止任务是由你来决定的。

网络请求部分

为了让任务管理器看起来更实用些。我封装了网络框架,实现是okhttp,能够支持head,get,post,多线程下载,大文件上传以及其它一些http请求。因为是面向接口编程,所以假设以后有更合适的库,能够非常方便的就换掉okhttp。这部分的样例我就不贴出来了,感兴趣能够自己看代码,非常easy,代码全在demo module的MainActivity里。

下载:



上传打文件:

最后

假设你有什么问题和建议能够留言或者给我发邮件。tractor是托管在github上,点击此处获取源代码。欢迎star or follow!

Android有用的任务管理器—tractor的更多相关文章

  1. android有用代码片段

    一.  获取系统版本号: [java] view plaincopy PackageInfo info = this.getPackageManager().getPackageInfo(this.g ...

  2. Android 有用的快捷键

    The powerful Android Studio 08 Jun 2016 Android Studio is the official tool for Android development ...

  3. Android开发网上的一些重要知识点[经验分享]

    1. android单实例运行方法 我们都知道Android平台没有任务管理器,而内部App维护者一个Activity history stack来实现窗口显示和销毁,对于常规从快捷方式运行来看都是s ...

  4. Android 程序员必须知道的 53 个知识点

    1. android 单实例运行方法 我们都知道 Android 平台没有任务管理器,而内部 App 维护者一个 Activity history stack 来实现窗口显示和销毁,对于常规从快捷方式 ...

  5. 我是怎样自学 Android 的?

    1. Java知识储备 本知识点不做重点解说: 对于有基础的同学推荐看<Java编程思想>,巩固基础,查漏补全,了解并熟悉很多其它细节知识点. 对于没有基础的同学推荐看一本Java基础的书 ...

  6. Android-ConvenientBanner轻松实现广告头效果

    Android-ConvenientBanner通用的广告栏控件,让你轻松实现广告头效果.支持无限循环, 可以设置自动翻页和时间(而且非常智能,手指触碰则暂停翻页,离开自动开始翻页. 你也可以设置在界 ...

  7. MTK 关闭安全模式

    1.当 Android 设备在安全模式(Safe Mode)下工作时,任何的第三方应用程序或相关文件(主要为apk应用程序文件)都不可以使用,但可以使用 Android 设备的任务管理器选项进行卸载或 ...

  8. flutter问题集锦

    现在的多平台开发很多啦,目前主流的救赎react native 和weex了,其他的旧的就不说了,新出来的gomobile目前基本无人使用,底层的很多原生对接还没有完善,flutter发布了第一版正式 ...

  9. 12套有用的免费 PSD 格式 Android UI 素材

    在这里,我们向大家呈现一些有用的和免费的 Android 用户界面 PSD 素材.由于 Android 市场迅速增长,设计人员和开发人员正在寻找一些快速和容易的方法来创建 Android 友好的应用和 ...

随机推荐

  1. amazeui学习笔记二(进阶开发3)--HTML/CSS规范Rules

    amazeui学习笔记二(进阶开发3)--HTML/CSS规范Rules 一.总结 1.am:以 am 为命名空间 2.模块状态: {命名空间}-{模块名}-{状态描述} 3.子模块: {命名空间}- ...

  2. invalid syntax 无效语法

    python用的是spyder编译器, 再出现上一行少了个括号的时候. 在下一行显示有错误.

  3. M1卡操作

    M1卡操作时,读取的时候,是将卡里面的1块(占16个字节)数据以十六进制字符的形式读取出来的啊!一个字节占两位16进制,因为读出来是字符.如果放在byte[]数组里,因为一个字符占一个字节,所以要用长 ...

  4. Fragment事务管理源代码分析

    转载请标明出处:http://blog.csdn.net/shensky711/article/details/53132952 本文出自: [HansChen的博客] 概述 在Fragment使用中 ...

  5. WCF REST (二)

    今天主要写下  POST等其他方式 发送请求 以及 流方式 文件的上传与下载 一.Post 提交数据 先来想下 POST和Get 的不同   Get 方式 我们直接通过 url  来传递参数   先来 ...

  6. Altium Designer如何移动选中的所有对象

    用shift去选中, 快捷键M S移动整体

  7. LA 3882 - And Then There Was One(约瑟夫 递归)

    看题传送门 题目大意: N个数排成一圈,第一次删除m,以后每k个数删除一次,求最后一被删除的数. 如果这题用链表或者数组模拟整个过程的话,时间复杂度都将高达O(nk),而n<=10000,k&l ...

  8. (转)yum & wget代理设置

    转自 http://www.cnblogs.com/windows/archive/2012/12/14/2817533.html   yum  配置代理服务器访问要设置所有 yum 操作都使用代理服 ...

  9. 重写ajax方法实现异步请求session过期时跳转登录页面(转)

    一般我们会在过滤器里判断登录状态,如果没登录就跳转登录页面,过滤器java核心代码如下: UserItem loginUser = (UserItem)request.getSession().get ...

  10. Springboot + shiro 整合之Url拦截设置(转)

    shiro 整合到springboot 还是比较简单的,只需要新建一个spring-shiro.xml的配置文件: <span style="font-size:14px;" ...