1. 程式人生 > >介面的使用,以及在非同步任務中的使用

介面的使用,以及在非同步任務中的使用

相信很多java和Android初學者,都對介面的定義有一些瞭解,但是如何使用它,利用它的特性來更好的實現自己想要的功能,卻不甚瞭解。之前,我寫程式碼也是沒怎麼用過介面,看到Android裡,如監聽方法裡實現介面的寫法,如:setOnClickListener(new OnClickListener(),或者網路請求的回撥方法等等。都用到介面,實現了回撥方法。這樣寫的好處,試過了就知道了。

好處一:在你想要實現某種功能(卻還不明確具體需求)的地方,你只需要在哪裡呼叫 介面的抽象方法,而具體的實現,你卻可以在你喜歡的其他地方實現。

例如:監聽方法的onclick回撥方法,它裡面的程式碼執行在點選事件完成後。仿寫一個:

//介面的定義
public interface Callbackinterface {
	void dosomethinFailed();
	void dosomethingSuceess();
}
<pre name="code" class="java">//介面的抽象方法呼叫的地方,這個例子裡在Bijiao類裡的方法裡通過判斷呼叫
public class Bijiao{
	
	public  void comprate(int a,int b,Callbackinterface callbackinterface){
		if (a>b) {
			callbackinterface.dosomethingSuceess();
		}else {
			callbackinterface.dosomethinFailed();
		}
	}
}


<pre name="code" class="java">//最後,在java的mian方法裡,呼叫Bijiao類的方法,並傳入一個實現的介面,就可以了,重寫的方法呼叫在上面的判斷裡,並執行
public class Test {
	public static void main(String[] args) {
		Bijiao bijiao=new Bijiao();
		bijiao.comprate(5, 4, new Callbackinterface() {
			
			@Override
			public void dosomethingSuceess() {
				// TODO Auto-generated method stub
				//dosomething you want
			}
			
			@Override
			public void dosomethinFailed() {
				// TODO Auto-generated method stub
				//dosomething you want
			}
		});
		
	}


	
<p>}</p>

顯然,通過介面你可以在回撥方法裡做你想做的事,而不用介面的話,你可能會將Bijiao類的的方法的程式碼寫死,不便於複用和修改。面向介面程式設計,也是一種解耦的不錯選擇。接下來,我們來做一個稍微複雜點的案例。我們的專案裡,總是會遇到很多非同步處理的需求,多執行緒來處理這些任務。通常,我們會用thread和handler,或者非同步任務來做這些事情。非同步任務和handler就挑非同步任務來說下吧,因為非同步任務本身也就是將thread和handler處理封裝了而已,而且,也用的是介面。在非同步任務AsyncTask裡,有兩個重要的重寫方法doInBackground和onPostExecute,分別就是工作執行緒和ui執行緒的操作了。

接下來,我想將非同步任務進一步通過實現一個介面,來使得這個非同步任務類跟適合複用。

//先定義一個介面,這個介面用來實現工作執行緒的執行程式碼
public interface BackgroundInit {
	boolean doinbackground();
	
}
//在定義一個介面,執行UI執行緒要執行的程式碼
public interface UiExecute {
	void onsucess();
	void onfailed();
}
//定義一個繼承AsyncTask的類
public class XpAsynncTask extends AsyncTask<Void, Void, Boolean>{
	UiExecute execute;
	BackgroundInit init;
	//構造方法傳入這兩個介面的實現類
	public XpAsynncTask(UiExecute execute,BackgroundInit init){
		this.execute=execute;
		this.init=init;
	}
	@Override
	protected Boolean doInBackground(Void... params) {
		// TODO Auto-generated method stub
		boolean result=false;
		result=init.doinbackground();//介面的抽象方法,具體實現在呼叫這個類的構造方法前實現
		return result;
	}

	@Override
	protected void onPostExecute(Boolean result) {
		// TODO Auto-generated method stub
		super.onPostExecute(result);
		if (result) {
			execute.onsucess();//介面的抽象方法,具體實現在呼叫這個類的構造方法前實現
		}else {
			execute.onfailed();//介面的抽象方法,具體實現在呼叫這個類的構造方法前實現
		}
	}
	

}

最後,在你要呼叫這個非同步任務處理的時候,你只需要如下,就不用每次都重寫一個非同步任務去修改doInBackground和onPostExecute裡的程式碼了。
<pre name="code" class="html">XpAsynncTask task=new XpAsynncTask(new UiExecute() {
				
				@Override
				public void onsucess() {
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public void onfailed() {
					// TODO Auto-generated method stub
					
				}
			}, new BackgroundInit() {
				
				@Override
				public boolean doinbackground() {
					// TODO Auto-generated method stub
					return false;
				}
			});
			task.execute();


同樣的,你還可以繼續在這個程式碼塊的某個地方再實現個介面,暴露給呼叫者實現的介面就當做方法的引數即可。就像我上面的寫法,就是給非同步任務嵌套了一層介面而已。

public void writeDataByYouself(UiExecute execute,
				final ProcessData processData) {//processData,再次增加的一個介面,這個介面只讓呼叫者新增資料,傳送的事情,我來做
			// TODO Auto-generated method stub
			XpAsynncTask task=new XpAsynncTask(execute,new BackgroundInit() {//BackgroundInit介面我不暴露給呼叫者去實現了

				@Override
				public boolean doinbackground() {
					// TODO Auto-generated method stub
					
					List<byte[]> list=processData.processDataBeforeSend();//processData,再次增加的一個介面,這個介面只讓呼叫者新增資料,傳送的事情,我來做
					if (list!=null) {
						for (int i = 0; i < list.size(); i++) {
							
							mMsg=xPrinterDev.Write(list.get(i));
						}
						if (mMsg.GetErrorCode().equals(ErrorCode.WriteDataSuccess)) {
							return true;
						}						
					}
					return false;
				}
			});
			//task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
			task.execute();
		}


</pre><pre>
恩,看了這幾個例子,你是不是發現,介面其實沒什麼,就是在另外一個方法裡,引數是這個介面的實現類,然後在方法體的某一個地方呼叫它的抽象方法吧了,說的簡單點,就是把一個程式碼塊換到了你想執行的地方去執行,而那個執行的地方用介面的抽象方法做了標記。沒錯,就是這麼簡單。

還有一點好處就是,如果你的非同步任務的子類,不是寫著Activity或者fragment裡的話,又想進行一些ui操作,怎麼辦,難道把要進行ui操作的控制元件和物件全部通過構造方法傳參過去?還是是個控制元件物件你就定義為靜態的?這樣肯定不怎麼好吧。那就用介面吧,在活動或者碎片裡,實現介面,就很容易解決這些問題。而這個非同步任務的子類也將具有非常高的複用性。程式碼結構也簡潔易懂。

這一篇就說那麼多了,下一篇,講下介面,service,非同步任務的結合使用情況。不忙的話。