zoukankan      html  css  js  c++  java
  • Android有用的任务管理器—tractor

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

    tractor基本的作用有:
    1. 代码变得整洁。不用在到处new Thread和new Handler。
    2. 能够监控任务的运行情况,能够随时取消一个或多个任务;
    3. 封装了okhttp。支持大文件上传,多线程断点下载。get,post以及其它的网络请求

    效果图

    效果图

    使用说明

    类图

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

    普通任务

    //当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!

  • 相关阅读:
    HDU-ACM“菜鸟先飞”冬训系列赛——第9场
    HDU3092:Least common multiple(素数筛选+完全背包)
    HDU1452:Happy 2004(积性函数)(因子和)
    HDU-ACM“菜鸟先飞”冬训系列赛——第8场(1004)
    Codeforces Round #395 (Div. 2)
    一些算法技巧整理(添加中)
    poj 1852 Ants
    hdu 1587 Flowers
    hdu 1563 Find your present!
    hdu 1570 AC
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/7257041.html
Copyright © 2011-2022 走看看