1. 程式人生 > >淺談Java回撥機制

淺談Java回撥機制

回撥機制讓我們程式碼執行更加高效,也讓我們程式碼變得非常的簡潔明瞭!

首先我們用個案例來一步一步帶入,當我們需要解析一段JSON字串時大部分我們的操作就是:

public class ParseJSON{
	private Entity parse(String json){
		*******解析部分省略*****
			return entity;
	}
}

我們要在呼叫時就會是:

public TActivity extends BaseActivity(){
	private ParseJSON parseJSON;
	private String json = "Your JSON String";
	private Entity entity;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		parseJSON = new ParseJSON();
		entity = parseJSON.parse(json);
	}
}

假設當我們的JSON足夠複雜,解析過程要3秒:
public class ParseJSON{
	private Entity parse(String json){
		*******解析部分省略*****
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return entity;
	}
}

這樣就會阻塞我們的主執行緒,然後有的同學就會說我們用新的子執行緒:

public class ParseJSON{
	private Entity parse(String json){
		*******解析部分省略*****
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}	
                                return entity;
			}
		}).start();
		
	}
}

這樣的話我們第一次返回的是null,而第二次才會返回解析的結果

原因:因為第一次請求得到的是還未賦值的空的物件,而第二次得到的是第一次解析後,賦給entity的值!

這就是開啟非同步請求獲取資料。

這時候我們就可以考慮使用回撥機制了,修改一下程式碼:

public class ParseJSON{
	private Entity parse(String json){
		*******解析部分省略*****
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}				
                                //解析完再傳回Activity
				Activity.onParseEnd(entity);
			}
		}).start();
		return entity;
	}
}

public TActivity extends BaseActivity(){
	private ParseJSON parseJSON;
	private String json = "Your JSON String";
	private Entity entity;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		parseJSON = new ParseJSON();
	}

	public void onParseEnd(Entity entity){
		this.entity = entity;
	}
}

上面就回調了Activity的方法,但是當我們解析出現錯誤時,如何通知Activity呢?

這時候我們可以用面向介面程式設計的思路來設計:

public interface OnParseListener{
        void onParseEnd(Entity entity);
        void onParseFail();
}
public class ParseJSON{
	private parse(String json,final OnParseListener parseListener){
		*******解析部分省略*****
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				try{
					parseListener.onParseEnd(entity);
				}catch(Exception e){
					parseListener.onParseFail();
				}
				
			}
		});
	}
}

這樣只有需要parse()方法的地方,實現OnParseListener介面就可以呼叫這個方法了
通過監聽回撥的形式進行解耦
public TActivity extends BaseActivity() implements OnParseListener{
	private ParseJSON parseJSON;
	private String json = "Your JSON String";
	private Entity entity;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		parseJSON = new ParseJSON();
		parseJSON.parse(json,this);
	}

	@Override
	public void onParseEnd(Entity entity){
		this.entity = entity;
	}

	@Override
	public void onParseFail(){
		Log.e("parse fail","..");
	}
}

我們還可以像寫onClick事件一樣,新增一個set方法即可:
public class ParseJSON{
	private OnParseListener parseListener;
	public void setOnParseListener(OnParseListener parseListener){
        this.parseListener = parseListener;
	}
	private parse(String json){
		*******解析部分省略*****
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				try{
					parseListener.onParseEnd(entity);
				}catch(Exception e){
					parseListener.onParseFail();
				}
				
			}
		});
	}
}
public TActivity extends BaseActivity() implements OnParseListener{
	private ParseJSON parseJSON;
	private String json = "Your JSON String";
	private Entity entity;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		parseJSON = new ParseJSON();
		parseJSON.setOnParseListener(new OnParseListener{
			@Override
			public void onParseEnd(Entity entity){
				entity = entity;
			}

			@Override
			public void onParseFail(){
				Log.e("parse fail","..");
			}
		});
		parseJSON.parse(json,this);
	}	
}

到這裡,我們的回撥機制就講完了,相信大家也有所有了解。

是不是覺得回撥機制讓程式碼變得更加效率簡潔了?那就get起來吧!

歡迎大家留言!