2012-11-19 51 views
2

我有一個相當棘手的情況,我試圖確定最好的設計。基本的是這樣的:IntentService android下載並返回文件到活動

  • 我正在設計一個類似郵件接口的郵件系統。
  • 當用戶點擊具有附件的郵件,活動被衍生,顯示該消息的用曲別針信令,有一個附加的附接沿着文本。
  • 此時,我開始預加載附件,以便當用戶點擊它時 - 加載速度更快。
  • 目前,當用戶點擊該附件,其與裝載對話框提示直到下載完成,在該點它加載一個單獨的附件查看器的活性,使BMP字節數組英寸
  • 我永遠不想將附件保存到持久性存儲。

我的困難是支持旋轉以及主頁按下按鈕等。下載目前使用線程和處理程序設置完成。

取而代之的是,我想的流動是下述:

  • 用戶如之前加載消息,附件的預加載開始之前(不可見的用戶)。
  • 當用戶單擊附件鏈接時,附件查看器活動即刻生成。
  • 如果下載完成,將顯示圖像。如果沒有,則會在THIS活動中顯示一個對話框,直到完成並顯示爲止。請注意,理想情況下,下載從不重新啓動,否則我浪費了預加載週期。

顯然我需要一些持續下載過程,並能夠回調到任意綁定的活動。看起來IntentService幾乎符合我的需求,因爲它在後臺線程中工作,並且具有Service(非UI)生命週期。但是,是否可以滿足我的其他需求?

我注意到我想要做的通用實現從調用者Activity獲取一個Messenger,以便Message對象可以發送回調用者線程中的Handler。這一切都很好,但在我的情況下,當調用者Activity停止或銷燬並且當前活動的Activity(附件查看器)正在顯示時會發生什麼? 有沒有一種方法可以將新的Activity動態綁定到正在運行的IntentService,以便我可以將消息發送回新的Activity?

另一個問題是消息對象上。我可以在這個包裏寄回任意大的數據嗎?例如,我不需要發回「文件已下載」,我需要發回已下載文件本身的字節數組,因爲我從不想將其寫入磁盤(並且是的,這需要是這種情況)。

上實現我想要的行爲任何意見是極大的讚賞。我不長的工作與Android對於我常常感到困惑着如何在活動週期的過程中最好地處理異步進程特別是當它涉及到方向變化和home鍵按下...

回答

2

有很多方法可以解決這個問題。你是對的,我認爲你顯然需要一個服務來解決這個場景,從可能來去的活動中分離下載過程。爲了這個工作,你需要在這個服務中實現一些下載隊列,並且IntentService提供了這種開箱即用的行爲,所以你可以使用它。 IntentService想到的唯一缺點是取消之前發佈的作業並不容易。

但是,我不會序列化下載的數據,但它聽起來不太有效,特別是如果您處理大量的二進制數據。您可以將下載的數據寫入內存LRU緩存,併爲其分配一個ID,查看器活動可以通過該ID來獲取該下載的數據。

您還可以使用廣播意圖通過服務發送查看器活動的信號,即具有特定ID的下載完成。這將確保觀看活動和下載服務之間的鬆散耦合。

所以它會去是這樣的:

  1. 用戶開放的消息attachement。
  2. 您將此附件的下載作業發佈到下載程序IntentService,併爲此附件指定唯一標識。
  3. 當用戶點擊附件時,您啓動Viewer Acitivty,並傳遞附件的唯一ID作爲此活動的參數。
  4. 查看器活動打開後,它會立即檢查緩存以顯示內容。如果尚未完成,它會顯示一些加載圖形,並等待下載程序IntentService使用廣播Intent喊出「xy ID已完成」。如果xy ID ==傳遞給此查看器活動的ID,您將從緩存中獲取現已完全下載的內容並將其呈現給用戶。

編輯:

至於緩存,你必須做出一些選擇。我認爲這是一個相當廣泛的話題,所以我只會在以前的項目基礎上寫一些想法。

上面我只提到了內存中的LRU緩存。這將住在一個自定義的應用程序對象,或作爲一個單身人士。哪個國家正在使用這個邪惡的全球國家,但我認爲在這樣的情況下這是合理的。優點是不需要將下載的數據序列化到任何位置:下載完成後,您將內容存儲在內存中,並且可以立即從查看器活動訪問它。缺點是,只有在不從該緩存中刪除該數據時,該數據纔可用,或者由於內存條件較低,系統不會中止應用程序的進程。

爲避免在您丟失此易失性內存中緩存的內容時重新下載數據,您需要爲其添加持久層。例如。將下載的數據寫入application's cache directory。這帶來了將下載的數據寫入磁盤的開銷,但至少您可以稍後訪問它,即使系統會導致您處理。您可以使用2級緩存方法將此永久緩存與內存緩存結合使用,也可以選擇其中一種。我建議查看一些廣泛使用的圖像下載器庫,以實現這種行爲以獲得靈感,例如, Universal Image Loader

+0

聽起來不錯,但是您對於全局可訪問的緩存有什麼想法?我認爲唯一能夠達到這個目的的是Application對象,但我確定這不是存儲此類事物的好地方。也許你的意思是我不瞭解的更低層次的東西? –

+0

我也加了一些編輯來解決緩存問題。 –

+0

偉大的寫作。非常感謝。 –

2

您使用一個IntentService將關閉,開始工作,然後將其發佈到一些持久性存儲中。要與活動進行通信,您可以在活動中使用廣播接收器,並從IntentService發送廣播意圖。

旋轉和主頁按鈕對IntentService沒有任何影響,只要它仍在工作,但旋轉將執行reDraw,並且主頁按鈕將暫停活動。出於這些原因,您應該避免在AsyncTask中進行異步工作,除非它不必完成並且不必持久化。

消息是處理程序,而不是組件。通過該系統傳輸信息的基本功能是Intents和廣播意圖。

IntentService只是處理將Intent轉變爲消息,創建新的HandlerThread,將消息放入HandlerThread的MessageQueue以及關閉Looper的工作。在後臺線程上執行的run()是onHandleIntent()中的任何東西(這有點簡化)。

+0

謝謝你的迴應。不幸的是我根本無法存儲到磁盤上,但是Zsombor的帖子可能會有漏洞。我談到的Messanger涉及從調用者Intent獲取EXTRA_MESSENGER屬性,並構造一個消息發送回其處理程序。這可能不是正確的方式 - 正如我所看到的那樣 –