Java - Asynchronous and callback example

非同步(Asynchronous)呼叫廣泛應用在UI的操作上,若是UI操作上已經送出一個請求,可是當下同時又可以執行其他工作,而在建立多個非同步處理的狀態,怎麼引導某一處理在得到結果後,回到一開始執行的地方去做其他工作呢? 由於是非同步的呼叫,因此我們無法等待它完成,只能由它主動告訴主程式已經完成了,所以在此搭配callback的概念來實作這個動作!

程式範例如下:
首先定義一下請求介面,分別為成功與失敗的處理
  1. public interface RequestMonitor {
  2. public void handleSuccess();
  3. public void handleFailure();
  4. }

再來透過實作請求介面,定義一個可以夾帶資料的抽象請求
  1. public class abstract DataRequestMonitor implements RequestMonitor{
  2. Object data;
  3. protected void setData(Object data) {
  4. this.data = data;
  5. }
  6. protected Object getData() {
  7. return this.data;
  8. }
  9. }

緊接著是模組,也就是處理請求的人。在此為單純的讀取檔案內容,並呼叫setData將內容傳進去;若是拋出IOException的話,則呼叫setData將getMessage()傳進去!
  1. public class Model {
  2. private static final Model INSTANCE = new Model();
  3. public static Model getInstance() {
  4. return INSTANCE;
  5. }
  6. public void execAsyncReadFile(final String filename, final DataRequestMonitor callback) {
  7. new Thread() {
  8. public void run() {
  9. try {
  10. callback.setData(readContents(filename));
  11. callback.handleSuccess();
  12. } catch (IOException e) {
  13. // TODO Auto-generated catch block
  14. callback.setData(e.getMessage());
  15. callback.handleFailure();
  16. }
  17. }
  18. }.start();
  19. }
  20. private String readContents(String filename) throws IOException {
  21. BufferedReader br = null;
  22. StringBuffer bf = new StringBuffer();
  23. try {
  24. br = new BufferedReader(new FileReader(filename));
  25. String line = null;
  26. while((line = br.readLine()) != null) {
  27. bf.append(line);
  28. }
  29. return bf.toString();
  30. }catch(IOException e) {
  31. throw e;
  32. }finally {
  33. if(br != null) {
  34. br.close();
  35. }
  36. }
  37. }
  38. }

最後定義主程式,由模組呼叫execAsyncReadFile並傳進檔案位置匿名類別,請注意這裡是anonymous class extend DataRequestMonitor,因此必須override handleSuccess()及handleFailure()
。所以並沒有實體化抽象類別DataRequestMonitor!
  1. public static void main(String[] args) {
  2. // TODO Auto-generated method stub
  3. new CallBackExample();
  4. }
  5. public CallBackExample() {
  6. Model model = Model.getInstance();
  7. String format = ".\\res\\%s.txt";
  8. for(int i = 0 ; i < 5 ; i++) {
  9. final String filename = String.format(format, i);
  10. model.execAsyncReadFile(filename, new DataRequestMonitor() {
  11. @Override
  12. public void handleSuccess() {
  13. // TODO Auto-generated method stub
  14. System.out.println("Parsing: "+filename+ " \nContents:"+getData());
  15. }
  16. @Override
  17. public void handleFailure() {
  18. // TODO Auto-generated method stub
  19. System.out.println("#Failure: "+ getData());
  20. }
  21. });
  22. }
  23. }

由於是非同步處理檔案讀取,因此在呼叫handleSuccess時可以表示檔案已經讀取完畢了!

DEMO如下:

留言