当前位置:操作系统 > 安卓/Android >>

Android 异步链式调用设计

考虑如下情况:

情况1:
访问网络(或其他耗时的事情)。通常的做法是:

1、显示一个ProgressDialog对话框,提示用户。

2、启动工作线程来执行耗时操作。

3、发送消息到关联到主线程的Handler里面,关闭对话框。

情况2:

从网络下载一个zip文件,下载完成之后,询问用户是否执行解压操作。通常的合理做法:

1、显示一个ProgressDialog对话框,提示用户。

2、启动线程执行下载操作。

3、发送消息到关联到主线程的Handler里面,关闭对话框,然后启动一个询问对话框。

4、用户如果点击[YES],显示一个ProgressDialog对话框。

5、启动用线程执行解压操作。

6、发送消息到关联到主线程的Handler里面,关闭对话框。

 


通常情况下,在Android我们有两种方式来使用线程,一是Thread + Handler这种标准方式,另外一种是使用AsyncTask类。

实现这两个情况的缺点:


1、定义Handler,发送消息,使得代码变得复杂,不易理解。

2、发送消息是异步处理,在某些情况下可能需要做等待操作。

3、流程执行混乱,不是流水作业。

基于以上情况,我们能不能也像流水线的操作那么调用我们的回调(Callback),使用者只关心第一步干什么,第二步干什么,如果能这样的话,那么在哪步做什么都能明确定义出来,这就是链式调用。


请看下面的链式调用的写法(JavaScript):


[java]
Async.go(initialArgument) 
   .next(firstAsyncOperation) 
   .next(secondAsyncOperation) 
   .next(thirdAsyncOperation) 
   .next(function(finalResult) { alert(finalResult); }) 

Async.go(initialArgument)
   .next(firstAsyncOperation)
   .next(secondAsyncOperation)
   .next(thirdAsyncOperation)
   .next(function(finalResult) { alert(finalResult); })

用户只需要添加每一步的task到一个队列里面,然后执行,这些task就会按添加的顺序执行,从而实现链式调用。

这种思想还不挺好的,在写代码的时候,我们更加关注实现的逻辑,不需要去考虑发什么消息等。只考虑第一步干什么,第二步干什么等。这样在以后代码维护时也比较好。

我们能不能设计出一个Android版本的异步链式调用的模块呢,请看下面。

Task

我们抽象出每一步要做的事情,定义一个Task类,它是一个抽象类,有如下核心属性和方法:

mRunInBackground
用来指示这个Task是运行在后台线程还是运行在主线程。

onExecuter(TaskOperation)
我们需要实现该方法,在这里面执行我们想要做的事情。

onProgressUpdate(Object)
我们可以重写该方法,来更新我们所做事情的进度,这个方法运行在主线程。

注意:在使用时,你必须指定这个Task是运行在UI线程还是后台线程。

 


TaskOperation

1)这个类里面包含了task的运行参数,上一个task的输出将会作为下一个task的输入。

2)它可以指示继续或暂停执行下一个task。

3)它里面使用了一个object[]来存储参数。

 


TaskManager
1)管理task队列,始终从队列第一个开始执行,执行一个task后,这个task将从队列出移除。

2)内部创建了一个带有消息循环的线程。

3)执行task时,判断其运行的线程环境,如果运行在UI线程,发送消息到UI的Handler来执行。

4)内部封装了Handler,用户不用关心是否发送消息。

5)核心方法有:
     - next(Task)
     - execute()
     - execute(TaskOperation)
     - cancelCurrentTask()
     - removeTasks()
     - publishProgress(Object)

这里只是给了一个最基本的设计思路,现在该设计还有完善的地方,具体的实现请参考相关的代码和测试工程。

 

实现代码
Task.java

[java]
/*
 * System: CoreLib
 * @version     1.00
 * 
 * Copyright (C) 2010, LiHong
 * 
 */ 
 
package com.nj1s.lib.task; 
 
import java.util.concurrent.atomic.AtomicBoolean; 
 
/**
 * <p>
 * This method define the task used to do something. Typically you should override
 * {@link #onExecute(TaskOperation)} method to do you things, on the other hand, you 
 * also can override the {@link #onProgressUpdate(Object)} method to get the progress of
 * you things.
 * </p>
 * 
 * <p>
 * NOTE:
 * There is an very important thing you should pay attention to, you must specify the task
 * is running on background thread or UI thread, the default flag is true ---- running on
 * background thread.
 * </p>
 * 
 * @author LeeHong
 * 
 * @date 2012/10/30
 */ 
public abstract class Task 

    /**
     * The id of the task, typically you need NOT set it, if will set automatically when you
     * add this task into {@link TaskManager} class.
     */ 
    private int             mId               = 0; 
     
    /**
     * The task name.
     */ 
    private String          mName             = null; 
     
    /**
     * Indicate this task is canceled or not.
     */ 
    private AtomicBoolean   mCancelled        = new AtomicBoolean(false); 
     
    /**
     * The task status, default value is {@link Status#PENDING}.
     */ 
    private volatile Status mStatus           = Status.PENDING; 
 
    /**
     * The running status, default value is {@link RunningStatus#UI_THREAD}.
     */ 
    private volatile RunningStatus mRunStatus = RunningStatus.UI_THREAD; 
     
    /**
     * Indicates the current status of the task. Each status will be set only once
     * during the lifetime of a task.
     */ 
    public enum Status  
    { 
        /**
         * Indicates that the task has not been executed yet.
         */ 
        PENDING, 
         
        /**
         * Indicates that the task is running.
         */ 
        RUNNING, 
         
        /**
         * Indicates that {@link Task#onExecute} has finished.
         */ 
        FINISHED, 
    } 
     
 

补充:移动开发 , Android ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,