日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Service和Thread的关系

發布時間:2025/6/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Service和Thread的关系 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

不少Android初學者都可能會有這樣的疑惑,Service和Thread到底有什么關系呢?什么時候應該用Service,什么時候又應該用Thread?答案可能會有點讓你吃驚,因為Service和Thread之間沒有任何關系!

之所以有不少人會把它們聯系起來,主要就是因為Service的后臺概念。Thread我們大家都知道,是用于開啟一個子線程,在這里去執行一些耗時操作就不會阻塞主線程的運行。而Service我們最初理解的時候,總會覺得它是用來處理一些后臺任務的,一些比較耗時的操作也可以放在這里運行,這就會讓人產生混淆了。但是,如果我告訴你Service其實是運行在主線程里的,你還會覺得它和Thread有什么關系嗎?讓我們看一下這個殘酷的事實吧。

在MainActivity的onCreate()方法里加入一行打印當前線程id的語句:

[java]?view plaincopy
  • Log.d("MyService",?"MainActivity?thread?id?is?"?+?Thread.currentThread().getId());??
  • 然后在MyService的onCreate()方法里也加入一行打印當前線程id的語句: [java]?view plaincopy
  • Log.d("MyService",?"MyService?thread?id?is?"?+?Thread.currentThread().getId());??
  • 現在重新運行一下程序,并點擊Start Service按鈕,會看到如下打印日志:

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    可以看到,它們的線程id完全是一樣的,由此證實了Service確實是運行在主線程里的,也就是說如果你在Service里編寫了非常耗時的代碼,程序必定會出現ANR的。

    你可能會驚呼,這不是坑爹么!?那我要Service又有何用呢?其實大家不要把后臺和子線程聯系在一起就行了,這是兩個完全不同的概念。Android的后臺就是指,它的運行是完全不依賴UI的。即使Activity被銷毀,或者程序被關閉,只要進程還在,Service就可以繼續運行。比如說一些應用程序,始終需要與服務器之間始終保持著心跳連接,就可以使用Service來實現。你可能又會問,前面不是剛剛驗證過Service是運行在主線程里的么?在這里一直執行著心跳連接,難道就不會阻塞主線程的運行嗎?當然會,但是我們可以在Service中再創建一個子線程,然后在這里去處理耗時邏輯就沒問題了。

    額,既然在Service里也要創建一個子線程,那為什么不直接在Activity里創建呢?這是因為Activity很難對Thread進行控制,當Activity被銷毀之后,就沒有任何其它的辦法可以再重新獲取到之前創建的子線程的實例。而且在一個Activity中創建的子線程,另一個Activity無法對其進行操作。但是Service就不同了,所有的Activity都可以與Service進行關聯,然后可以很方便地操作其中的方法,即使Activity被銷毀了,之后只要重新與Service建立關聯,就又能夠獲取到原有的Service中Binder的實例。因此,使用Service來處理后臺任務,Activity就可以放心地finish,完全不需要擔心無法對后臺任務進行控制的情況。

    一個比較標準的Service就可以寫成:

    [java] view plaincopy
  • @Override??
  • public?int?onStartCommand(Intent?intent,?int?flags,?int?startId)?{??
  • ????new?Thread(new?Runnable()?{??
  • ????????@Override??
  • ????????public?void?run()?{??
  • ????????????//?開始執行后臺任務??
  • ????????}??
  • ????}).start();??
  • ????return?super.onStartCommand(intent,?flags,?startId);??
  • }??
  • ??
  • class?MyBinder?extends?Binder?{??
  • ??
  • ????public?void?startDownload()?{??
  • ????????new?Thread(new?Runnable()?{??
  • ????????????@Override??
  • ????????????public?void?run()?{??
  • ????????????????//?執行具體的下載任務??
  • ????????????}??
  • ????????}).start();??
  • ????}??
  • ??
  • }??

  • 創建前臺Service

    Service幾乎都是在后臺運行的,一直以來它都是默默地做著辛苦的工作。但是Service的系統優先級還是比較低的,當系統出現內存不足情況時,就有可能會回收掉正在后臺運行的Service。如果你希望Service可以一直保持運行狀態,而不會由于系統內存不足的原因導致被回收,就可以考慮使用前臺Service。前臺Service和普通Service最大的區別就在于,它會一直有一個正在運行的圖標在系統的狀態欄顯示,下拉狀態欄后可以看到更加詳細的信息,非常類似于通知的效果。當然有時候你也可能不僅僅是為了防止Service被回收才使用前臺Service,有些項目由于特殊的需求會要求必須使用前臺Service,比如說墨跡天氣,它的Service在后臺更新天氣數據的同時,還會在系統狀態欄一直顯示當前天氣的信息,如下圖所示:

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    那么我們就來看一下如何才能創建一個前臺Service吧,其實并不復雜,修改MyService中的代碼,如下所示:

    [java] view plaincopy
  • public?class?MyService?extends?Service?{??
  • ??
  • ????public?static?final?String?TAG?=?"MyService";??
  • ??
  • ????private?MyBinder?mBinder?=?new?MyBinder();??
  • ??
  • ????@Override??
  • ????public?void?onCreate()?{??
  • ????????super.onCreate();??
  • ????????Notification?notification?=?new?Notification(R.drawable.ic_launcher,??
  • ????????????????"有通知到來",?System.currentTimeMillis());??
  • ????????Intent?notificationIntent?=?new?Intent(this,?MainActivity.class);??
  • ????????PendingIntent?pendingIntent?=?PendingIntent.getActivity(this,?0,??
  • ????????????????notificationIntent,?0);??
  • ????????notification.setLatestEventInfo(this,?"這是通知的標題",?"這是通知的內容",??
  • ????????????????pendingIntent);??
  • ????????startForeground(1,?notification);??
  • ????????Log.d(TAG,?"onCreate()?executed");??
  • ????}??
  • ??
  • ????.........??
  • ??
  • }??

  • 這里只是修改了MyService中onCreate()方法的代碼。可以看到,我們首先創建了一個Notification對象,然后調用了它的setLatestEventInfo()方法來為通知初始化布局和數據,并在這里設置了點擊通知后就打開MainActivity。然后調用startForeground()方法就可以讓MyService變成一個前臺Service,并會將通知的圖片顯示出來。

    現在重新運行一下程序,并點擊Start Service或Bind Service按鈕,MyService就會以前臺Service的模式啟動了,并且在系統狀態欄會彈出一個通欄圖標,下拉狀態欄后可以看到通知的詳細內容,如下圖所示。

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    總結

    以上是生活随笔為你收集整理的Service和Thread的关系的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。