2012-04-26 75 views
36

我正在使用IntentService通過JSON處理與服務器的網絡通信。 JSON /服務器部分工作正常,但我無法將結果返回到需要的地方。以下代碼顯示了我如何從onClick()開始啓動intent服務,然後讓服務更新全局變量以將結果轉發回主活動。如何將IntentService的結果返回到活動中?

public class GXActivity extends Activity { 

    private static final String TAG = "GXActivity"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     // === called when the activity is first created 

     Log.i(TAG, "GXActivity Created"); 

     super.onCreate(savedInstanceState); 
     setContentView(R.layout.start); 

     View.OnClickListener handler = new View.OnClickListener() { 
      public void onClick(View v) { 

       // === set up an application context to hold a global variable 
       // === called user, to contain results from the intent service 
       GXApp appState = ((GXApp) getApplicationContext()); 
       User user = new User(-1); // initialize user id to -1 
       appState.setUser(user); 

       // === next start an intent service to get JSON from the server; 
       // === this service updates the user global variable with 
       // === results from the JSON transaction 
       Intent intent = new Intent(this, GXIntentService.class); 
       startService(intent); 

       // === check app context for results from intent service 
       appState = ((GXApp) getApplicationContext()); 
       if (appState.getUser().getId() != -1)... 

      } 
     } 
    } 
} 

我遇到的問題是,解析JSON的意圖服務沒有得到後的onCreate()完成調用到,所以我的代碼,在尋找的結果是停留在看未初始化的結果。

我應該做什麼不同,以便在檢查結果之前調用intent服務?如果我將click監聽器從onCreate()函數中取出,它會起作用嗎?有沒有其他的/更好的結構代碼?非常感謝。

+1

看到這可能會有所幫助http://stackoverflow.com/a/9089086/985143 – 2012-04-26 14:01:34

回答

78

你應該看看在你的活動中創建自己的ResultReceiver子類。 ResultReceiver implements Parcelable因此可以從Activity傳遞到Service作爲Intent的附加內容。

你需要做這樣的事情:

  1. 您的活動類中實現的ResultReceiver一個子類。實施的關鍵方法是onReceiveResult()。此方法爲您提供Bundle結果數據,可用於傳遞您在Service中檢索的任何信息。只需解開您需要的數據並使用它來更新您的活動。

  2. 在您的活動中,創建自定義ResultReceiver的新實例並將其添加到您用於啓動服務的Intent

  3. 在你ServiceonStartCommand()方法,檢索有關Intent傳入的ResultReceiver並將其存儲在本地成員變量。

  4. 一旦Service完成其工作,有它調用send()的ResultReceiver傳遞要發送回活動的Bundle任何數據。

這是一個非常有效的模式,並且意味着你不會將數據存儲在討厭的靜態變量中。

+0

感謝您的快速回復!兩個後續問題。首先,如果我按照你的建議切換到使用意向附加程序,那麼你有一個很好的,簡單的代碼示例嗎?其次,如果我想堅持使用全局變量方法(在這種情況下,它是相當無害的,因爲它所保存的數據不會非常頻繁地或非常頻繁地發生變化),我該怎麼做呢?有沒有辦法將click監聽器從onCreate()中提取出來,否則會同步Activity和Service? – gcl1 2012-04-26 14:18:52

+0

您遇到的根本問題是服務完全獨立於活動運行並需要花費不確定的時間來完成。這個問題的「正確」解決方案是使用某種異步回調機制(這是ResultReceiver爲您所做的)。另一種方法是反覆輪詢活動中的某種「isRunning」靜態變量,以檢測服務何時完成,然後從另一個靜態變量讀取數據。這是相當低效的,但可能需要一個專用的後臺線程 - 不推薦。 – tomtheguvnor 2012-04-26 14:29:25

+0

我試過了,但剛從這裏開始,顯然還沒有足夠的聲望點。但你的回答非常好,並且破解了讓我一直持續到昨天凌晨3點的堅果。謝謝! – gcl1 2012-04-27 01:15:22

7

如果您只需要從服務器獲取JSON而不鎖定UI線程,那麼使用AsyncTask可能會更簡單。

+2

異步任務生命週期綁定到它正在運行的線程,所以如果我旋轉屏幕它將重新啓動! – hadi 2015-11-05 15:09:05

11

有許多方法可以在後臺獲取結果(AsyncTask,將活動綁定到服務...),但如果你想你的十個分量IntentService的代碼,你可以簡單地說:

1發送廣播意圖(包含在其擴展數據的狀態),在工作結束在IntentService

2-實現你的活動LocalBroadcastReceiver消耗從意向

的數據,這也是官方文檔以建議的方式(如果你想你的十個分量IntentService):

https://developer.android.com/training/run-background-service/report-status.html

1

您可以使用Otto庫。 Otto是一個開源項目,旨在提供事件總線實現,以便組件可以發佈和訂閱事件。

+0

不知道Otto或GreenBus是否可以在IntentService的線程中工作。 – Genc 2016-09-02 11:52:07

+0

它的工作原理。我一直在使用。 – 2016-09-02 12:55:10

相關問題