最近在做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。