介面的使用,以及在非同步任務中的使用
相信很多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,非同步任務的結合使用情況。不忙的話。