最近在做Android项目时遇到这样一个问题:客户端向服务器请求数据,而在网络信号太差的情况下,数据迟迟不到,甚至丢失。服务器为了解决这个问题做了频繁的重发,android 客户端就会收到很多不想要的消息;或者因为消息回来太慢,用户已经失去耐心的去做别的操作了,而那个姗姗来迟的消息的到来就会让用户莫名其妙。
如何有一个类,在向服务器发出请求的时候就向任务队列中添加一条任务,并启动,等待时间到了以后就丢弃这个任务;在等待时间内如果有相应的响应消息返回的时候,则停掉该任务就解决了这一难题了。
下面是任务类:
1 import java.util.TimerTask; 2 3 public class MsgTask extends TimerTask { 4 private long deltaTime; //时间增量,及任务执行等待时间 5 private MsgKey msgKey; 6 private MsgProcessor msgProcessor = new MsgProcessor(); 7 8 public MsgTask(MsgKey msgKey,long deltaTime) { 9 super(); 10 this.msgKey = msgKey; 11 this.deltaTime = deltaTime; 12 } 13 14 public long getDeltaTime() { 15 return deltaTime; 16 } 17 18 public void setDeltaTime(long deltaTime) { 19 this.deltaTime = deltaTime; 20 } 21 22 public MsgKey getMsgKey() { 23 return msgKey; 24 } 25 26 public void setMsgKey(MsgKey msgKey) { 27 this.msgKey = msgKey; 28 } 29 30 @Override 31 public void run() {//等待时间到了以后,就执行 32 int index = msgKey.getIndex(); 33 msgProcessor.dealOverTimeMsg(index); 34 MsgManager.removeMsgTask(msgKey); 35 this.cancel(); 36 } 37 }
为了方便对任务队列的管理,可以写一个任务管理类:
1 import java.util.Collections; 2 import java.util.HashMap; 3 import java.util.Map; 4 import java.util.Timer; 5 6 import android.util.Log; 7 8 public class MsgManager { 9 private static Timer timer = new Timer(); 10 private static Map<MsgKey, MsgTask> msgTasks = Collections.synchronizedMap(new HashMap<MsgKey, MsgTask>()); 11 12 public static void putMsgTask(MsgKey msgKey,MsgTask msgTask) { 13 synchronized (msgTasks) { 14 msgTasks.put(msgKey, msgTask); 15 } 16 } 17 18 public static void startMsgTask(MsgKey msgKey,MsgTask msgTask) { 19 putMsgTask(msgKey, msgTask); 20 timer.schedule(msgTask, msgTask.getDeltaTime()); 21 Log.d("zyr",""+msgKey.getIndex()); 22 } 23 24 public static MsgTask removeMsgTask(MsgKey msgKey) { 25 MsgTask msgTask = null; 26 synchronized (msgTasks) { 27 msgTask = msgTasks.remove(msgKey); 28 } 29 return msgTask; 30 } 31 32 public static boolean stopMsgTask(MsgKey msgKey) { 33 MsgTask msgTask = removeMsgTask(msgKey); 34 if (msgTask != null){ 35 msgTask.cancel(); 36 return true; 37 } 38 return false; 39 } 40 }
任务需要一个标志,才能方便启动和结束,下面的MsgKey就是用来标记任务的实体类:
1 public class MsgKey { 2 private int index; 3 4 public int getIndex() { 5 return index; 6 } 7 8 public void setIndex(int index) { 9 this.index = index; 10 } 11 12 @Override 13 public boolean equals(Object obj) { 14 if (obj instanceof MsgKey) { 15 MsgKey msgKey = (MsgKey) obj; 16 return this.index == msgKey.getIndex(); 17 } else { 18 return false; 19 } 20 } 21 22 @Override 23 public int hashCode() { 24 return String.valueOf(this.index).hashCode(); 25 } 26 }
当然,如果等待超时,一定要有相应的处理的:
1 public class MsgProcessor { 2 3 /** 4 * 处理超时的消息 5 * @param index 6 */ 7 public void dealOverTimeMsg(int index){ 8 switch (index) { 9 case 0: 10 loginOverTimeHandler(); 11 break; 12 13 default: 14 break; 15 } 16 } 17 18 private void loginOverTimeHandler(){ 19 //这里写处理方法 20 } 21 }
值得注意的是:如果需要把任务添加到任务队列后并立即执行,则用startMsgTask方法,结束这个任务时要用stopMsgTask方法,如果没有这个任务 stopMsgTask返回false;如果需要把任务添加到任务队列但不确定什么时候执行,则用putMsgTask方法,结束这个任务时就用removeMsgTask方法就可以了,如果没有这个任务removeMsgTask返回null。