2015-11-10 83 views
0

我正在實施Android中的客戶端,並進行了翻新。 由於我使用異步請求,客戶端處理單獨線程中的每個請求,然後我在回調中得到答案。處理活動內部連接回調的最佳做法

它看起來是這樣的:

public void request(){ 


    ThisService client = ServiceGenerator.createService(ThisService.class,baseUrl); 

    client.request(new Callback<Answer>() { 
     @Override 
     public void success(LoginAnswer answer, Response response) { 

     } 

     @Override 
     public void failure(RetrofitError error) { 

     } 
    }); 

} 

我需要做的是,回調後,改變一些UI設置是什麼,所以我所做的是要實現我的活動靜態方法:

public static void changeUI(){} 

這樣在回調,我可以這樣做:

public void request(){ 


    ThisService client = ServiceGenerator.createService(ThisService.class,baseUrl); 

    client.request(new Callback<Answer>() { 
     @Override 
     public void success(LoginAnswer answer, Response response) { 
      Activity.changeUI(); 
     } 

     @Override 
     public void failure(RetrofitError error) { 

     } 
    }); 

} 

的問題是,做thigs的方法是讓我爲Activity定義很多靜態變量和方法(從靜態方法我只能調用其他靜態方法或訪問靜態變量)。 因此,例如,如果來自changeUI(),我想調用另一個Activity方法,它必須是靜態的,等等。

如果例如我想完成活動,我不能調用finish(),因爲這不是靜態的。

我想我想問的是:什麼是避免這種情況的最好方法?

我在網上看到的每個例子都是在成功方法中實現的,但它對我來說似乎並不「乾淨」。

我在想像單例模式,在那裏我可以調用getInstance(),一個返回活動副本的靜態方法,然後爲UI更改定義非靜態方法。

回答

0

您可以使用LocalBroadcastManager

聲明接收器的UI元素中

private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
      // do whatever you ui needs to update 
     } 
    } 
}; 

,並從你的任務由

@Override 
protected void onStart() { 
    super.onStart(); 
    final IntentFilter filter = new IntentFilter("nameOfYourFilterAction"); 
    LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, filter); 
} 

@Override 
protected void onStop() { 
    LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver); 
    super.onStop(); 
} 

聽從你的UI元素的任何廣播,你只需簡單地發送新的意圖對象

final Intent broadcast = new Intent("nameOfYourFilterAction"); 
broadcast.put(<any extras>); 
LocalBroadcastManager.getInstance(<some context>).sendBroadcast(broadcast); 
4

我喜歡通過在我的網絡類中定義自定義回調接口來處理這些情況,然後將消息直接發送給需要它的人。舉個例子,假設你有一個名爲YourCallbackClass的類來完成一些網絡操作。我們將這樣定義它:

public class YourCallbackClass { 

    YourNetworkCallbacks callback; 

    public YourCallbackClass(YourNetworkCallbacks callback) { 
     this.callback = callback; 
    } 

    public void networkMethod() { 
     String message = "This came from YourCallbackClass"; 
     callback.networkCallback(message); 
    } 

    public interface YourNetworkCallbacks { 
     public void networkCallback(String message); 
    } 
} 

在這個類中,我們定義了一個名爲YourNetworkCallbacks公共接口,只有一個方法。此方法將用於將我們的網絡操作結果發送回調用類。我們的網絡方法只是一種定義爲networkMethod()的虛擬方法。它只是產生一個我們發送給我們的調用類的字符串。

所以爲了讓這個字符串到另一個類,我們必須讓我們的調用類實現公共接口YourNetworkCallbacks。所以,我們的活動是希望網絡操作的結果將是這個樣子的頂部:

public class MainActivity extends AppCompatActivity implements YourCallbackClass.YourNetworkCallbacks { 
    ... 
    ... 

現在我們要做的就是真正實現我們在YourNetworkCallbacks定義的回調方法。因此,在MainActivity中,我們簡單地說:

public void networkCallback(String message) { 
    Log.d("NETWORK CALLBACK", "A message from YourCallbackClass: "+message); 
} 

而我們的回調的這個實現現在已準備好接收消息。現在我們所要做的就是告訴YourCallbackClass誰在監聽我們的回調,因此它知道在哪裏路由消息。我們通過傳入一個監聽器實例來完成此任務,該監聽器實例只是實現回調的任何類。在這種情況下,我們的MainActivity按照定義實現了回調,因此我們可以在創建YourCallbackClass的實例時發送this。所以我們會做:

YourCallbackClass callbackClass = new YourCallbackClass(this); 

你會在YourCallbackClass看到,我們採取這個監聽器傳遞進來(這僅僅是我們的活動本身,它實現了回調的一個實例),我們指定參考我們的擁有本地回調變量。這樣做可以讓我們現在將消息發送到回調引用,該引用實際上是MainActivity中回調的引用。這有效地讓我們直接與MainActivity溝通!

所以現在將消息發送回MainActivity,我們簡單地做:

public void networkMethod() { 
    String message = "This came from YourCallbackClass"; 
    callback.networkCallback(message); 
} 

你會實現這個爲自己的項目的方式,就是你必須從你的網絡操作的回調使這個呼叫您自己的自定義回調,這些回調在您想要獲取信息的任何活動/類中實現。這一切都非常混亂,但一旦你掌握了這一點,你很快就會意識到在處理異步操作時,一個強大的工具回調是什麼!

希望這回答你的問題!


編輯迴應評論: 好了,讓我們來談談你將如何實現自己的項目該解決方案。你顯然有一些課程正在進行網絡操作,並且你提到你正在回調網絡結果,對吧?

因此,您的網絡操作類是您的「YourCallbackClass」版本。因此,在您的網絡操作類中,定義公共接口並添加一個名爲「sendNetworkResults()」的方法或任何您想要的接口定義。同樣在你的網絡操作類中,你需要創建一個私有成員,它是你的接口的一個實例。因此,在你的網絡操作類中,你應該定義接口,並且是一個私有成員,它是你的回調接口的一個實例(在上面的例子中,你將它看作「YourNetworkCallbacks callback;」)。

現在在希望獲得網絡結果的Activity中,讓Activity類實現您在網絡操作類中定義的接口。因此,您需要爲類定義添加「implements」,並且您需要實際實現在界面中定義的sendNetworkResults()方法。

現在您的活動全部設置爲接收回調,並且您的網絡操作類都設置爲發送回調。剩下的唯一要做的就是連接兩個來完成橋樑。因此,我們通過將您的Activity的實例分配給您在網絡操作類中創建的回調成員來完成此操作。在我上面的例子中,這是YourNetworkCallbacks callback;成員。您可以通過將Activity傳遞給網絡操作構造函數(我在示例中使用它)來完成此操作。或者你可以在你的網絡操作類中創建一個setter方法,如setNetworkClassListener(YourNetworkCallbacks callback);

一旦你做了這個任務,你只需要發送消息給這個回調成員,它會自動發送結果給你在Activity中實現的方法。那麼你如何做到這一點?

你提到你正在爲你的網絡結果得到一個回調。因此,當回調進入時,您只需通過調用您在界面中定義的方法,在我們分配的回調成員上將相關信息傳遞給您的活動。因此,這將是這樣的:

//This is the callback that gets called when your network results come in 
public void yourNetworkOperationCallback(String someValue) { 

    /** 
    * Now we take the String result that returned from the network callback 
    *and we pass it on to the Activity by sending it into our interface method 
    *using the callback reference we assigned. Here, "callback" is a member 
    * we defined for this class, and we assigned it the value of our Activity 
    * instance. 
    **/ 
    callback.sendNetworkResults(someValue); 
} 

還記得我們指定成員callback我們的活動,它實現了接口的值。所以我們基本上是說Activity是我們回調的一個實例,我們只是將引用複製到我們的本地回調變量中。所以現在當我們調用sendNetworkResults()方法時,它會轉到我們引用的實現,這是我們的Activity。

所以,你的網絡的回調應該是這個樣子:

public void request(){ 


    ThisService client = ServiceGenerator.createService(ThisService.class,baseUrl); 

    client.request(new Callback<Answer>() { 
     @Override 
     public void success(LoginAnswer answer, Response response) { 
      //We're passing these values directly to Activity 
      callback.sendNetworkResult(answer, response); 
     } 

     @Override 
     public void failure(RetrofitError error) { 

     } 
    }); 

} 

然後在你的活動,你有sendNetworkResults()方法實現的,所以它看起來是這樣的:

public void sendNetworkResults(LoginAnswer answer, Response response) { 
    //This is implemented in your Activity. So now just update your Activity UI 
    //with the answer and response values! 
} 

現在你在您的活動中有answerresponse值!剩下要做的就是用它們來更新你的用戶界面。

希望這一切都有道理。我知道這是超級混亂:)

+0

很好的解釋,我認爲正是我需要的。讓我執行它,我會告訴你它是否工作。謝謝! – user3013172

+0

我還是不明白。我如何從網絡操作的回調中調用networkMethod()?我必須在那裏實例化一個YourCallbackClass對象嗎? 或者我想我必須把對象給網絡操作。 – user3013172

+0

@ user3013172 - 查看我上面的修改。我試圖儘可能清楚地解釋它。我知道這件事起初非常混亂,如果需要,隨時可以提出更多問題。我很樂意提供幫助! – NoChinDeluxe