2013-08-18 90 views
11

我建立一個Android應用程序與定期的服務器,只要應用程序正在運行通信與服務器通信。最佳實踐來使用線程

我爲此通過發起與服務器的連接時,應用程序開始,然後我有用於接收稱爲ReceiverThread消息單獨thread,這thread讀取來自socket消息,分析它,並將其轉發到適當的部分的應用程序。

這個thread運行在一個循環中,讀取任何需要讀取的內容,然後在read()命令上阻塞,直到新數據到達,所以它花費了大部分時間。

我處理,通過不同的線程中發送消息,稱SenderThread。我想知道的是:我應該以類似的方式構建SenderThread嗎?這意味着我應該保持某種形式的隊列這個線程,讓它發出的所有消息隊列,然後阻塞,直到新郵件進入隊列,或者我應該只是啓動線程的新實例每個需要發送郵件時,讓它發送消息,然後「死」?我傾向於第一種方法,但我不知道究竟是好無論是在性能方面(保持阻塞的線程在內存與初始化新線程),並在代碼的正確性方面。

此外,由於所有的活動都需要能夠發送和接收我的Application類,我抱着兩個線程參考消息,是一個可以接受的方法,或者我應該有不同的實現呢?我曾與此遇到

的一個問題是,有時如果我關閉我的應用程序並再次運行它實際上我ReceiverThread的兩個實例,讓我得到一些消息的兩倍。

我猜測,這是因爲我的應用程序實際上並沒有關閉與前一個線程仍然活躍的(被阻擋在read()操作),當我再次打開該應用程序的線程被初始化,但都被連接到服務器使服務器將消息發送給兩者。有關如何解決此問題的任何提示,或有關如何徹底重新組織它以確保正確的提示?

我試圖查找這些問題,但發現我的第一個問題,一些相互矛盾的例子,並沒有什麼是足夠有用,適用於我的第二個問題...

+0

「關閉」了應用程序並沒有真正殺死它。它只是繼續運行,尤其是線程不會自動停止 – zapl

+0

@zapl是的我意識到這一點,這是我的問題。問題是:如何可靠地停止線程?或者如何以避免此問題的方式實施相同的整體應用程序? – Bob

+0

這確實很棘手。 'Thread#interrupt()'(+'Socket#close()')可以用來停止它,但最難的部分是跟蹤應用程序是在運行還是在後臺閒置。例如,每個活動都可以從'onStop'上的'onStart'完成。 – zapl

回答

17

你的做法是好的,如果你真的需要保持服務器和客戶端之間的所有時間,不惜一切代價的開放連接。不過我會用一個異步連接,比如發送一個HTTP請求到服務器,然後得到的答覆每當服務器感覺它。

如果您需要服務器稍後回覆客戶端,但您不知道何時,還可以查看Google Cloud Messaging framework,它可以爲您提供透明且一致的向客戶端發送小消息的方式從你的服務器。

您需要考慮一些事情,當你正在開發一個移動應用程序。

  1. 智能手機沒有無窮的電量。

  2. 智能手機的互聯網連接是有點揮發,你將失去在不同時間的互聯網連接。

當你把一個直接連接到服務器的時候,您的應用程序保持發送保活分組,這意味着你吸手機乾燥非常快。 當互聯網連接與移動寬帶一樣不穩定時,您有時會失去連接並需要從中恢復。所以如果你使用TCP是因爲你想確保你的數據包被接收到,你會重發相同的數據包很多次,所以會產生很多開銷。

如果你自己打開服務器上的線程,聽起來像是你也可能會遇到服務器端的線程問題。假設您有200個客戶端同時連接到服務器。每個客戶端在服務器上有1個線程打開。如果服務器需要同時處理200個不同的線程,那麼這對於服務器來說可能是一項非常耗費性能的任務,並且您還需要自行完成很多工作。

2.當你退出你的應用程序時,你需要在你之後進行清理。這應該在Activity的方法中進行,該方法處於活動狀態。

這意味着,殺死了所有活動線程(或至少interupting他們),節省您的UI的狀態(如果你需要這個)和沖洗和關閉到您在服務器的任何打開的連接。

至於使用Threads推移,我會建議使用一些內置的線程工具像Handlers或實施​​。

如果你真的認爲Thread是要走的路,我肯定會推薦使用Singleton pattern作爲你的線程的「經理」。

這位經理將控制你的線程,這樣你就不會超過一個Thread在任何給定時間談論到服務器,即使你在應用程序的另一部分是結束了。

至於Application類實現去,看看在Application class documentation

基類爲那些誰需要保持全球應用程序狀態。您可以通過在您的AndroidManifest.xml標籤中指定其名稱來提供您自己的實現,這將在您的應用程序/軟件包創建過程中爲您實例化該類。

通常不需要繼承應用程序。在大多數情況下,靜態單例可以以更模塊化的方式提供相同的功能。

因此保持距離實現自己的Application類遠建議,但是如果你讓你的Activities的一個初始化自己Singleton類管理Threads和連接你可能(只是可能)碰到麻煩,因爲初始化的單身人士可能會「綁定」到特定的Activity,所以如果特定的Activity被從屏幕上移除並暫停,它可能會被殺死,因此單身人士也可能會被殺死。因此,在您的Application實施中初始化單身人士可能認爲有用。

對不起,文字的牆,但你的問題是相當「開放式」,所以我想給你一個有點開放式的問題 - 希望它可以幫助;-)

+0

謝謝,儘管我仍然不完全確定要做什麼,但您的答案確實有幫助。我知道開發移動電話有很多方面,比如保持電池壽命,但是由於我的應用使用情況,我確實需要不斷的連接。應用程序使用率通常應該很短,通常5分鐘就足夠了,但是在這5分鐘內應該會發生許多互聯網上的交互。我真的不認爲保持連接5分鐘會使電池變幹,對嗎? – Bob

+0

@Bob 5分鐘很好。定期更新背景是有問題的。請參閱http://developer.android.com/training/efficient-downloads/index.html – zapl