android-Service和Thread的区别
1.服務不是單一的進程。服務沒有自己的進程,應用程序可以不同,服務運行在相同的進程中。
2.服務不是線程。可以在線程中工作。
一.在應用中,如果是長時間的在后臺運行,而且不需要交互的情況下,使用服務。
同樣是在后臺運行,不需要交互的情況下,如果只是完成某個任務,之后就不需要運行,而且可能是多個任務,需需要長時間運行的情況下使用線程。
二.如果任務占用CPU時間多,資源大的情況下,要使用線程。
?
servie是系統(tǒng)的組件,它由系統(tǒng)進程托管(servicemanager);它們之間的通信類似于client和server,是一種輕量級的ipc通信,這種通信的載體是binder,它是在linux層交換信息的一種ipc。而thread是由本應用程序托管。
?
1).?Thread:Thread?是程序執(zhí)行的最小單元,它是分配CPU的基本單位。可以用Thread?來執(zhí)行一些異步的操作。
?
2).?Service:Service?是android的一種機制,當它運行的時候如果是Local?Service,那么對應的Service?是運行在主進程的main?線程上的。如:onCreate,onStart?這些函數(shù)在被系統(tǒng)調(diào)用的時候都是在主進程的main?線程上運行的。如果是Remote?Service,那么對應的Service?則是運行在獨立進程的main?線程上。
?
既然這樣,那么我們?yōu)槭裁匆肧ervice?呢?其實這跟android?的系統(tǒng)機制有關,我們先拿Thread?來說。Thread?的運行是獨立于Activity?的,也就是說當一個Activity?被finish?之后,如果你沒有主動停止Thread?或者Thread?里的run?方法沒有執(zhí)行完畢的話,Thread?也會一直執(zhí)行。因此這里會出現(xiàn)一個問題:當Activity?被finish?之后,你不再持有該Thread?的引用。另一方面,你沒有辦法在不同的Activity?中對同一Thread?進行控制。
?
舉個例子:如果你的Thread?需要不停地隔一段時間就要連接服務器做某種同步的話,該Thread?需要在Activity?沒有start的時候也在運行。這個時候當你start?一個Activity?就沒有辦法在該Activity?里面控制之前創(chuàng)建的Thread。因此你便需要創(chuàng)建并啟動一個Service?,在Service?里面創(chuàng)建、運行并控制該Thread,這樣便解決了該問題(因為任何Activity?都可以控制同一Service,而系統(tǒng)也只會創(chuàng)建一個對應Service?的實例)。
?
因此你可以把Service?想象成一種消息服務,而你可以在任何有Context?的地方調(diào)用Context.startService、Context.stopService、Context.bindService,Context.unbindService,來控制它,你也可以在Service?里注冊BroadcastReceiver,在其他地方通過發(fā)送broadcast?來控制它,當然這些都是Thread?做不到的。
---------------------------------------------------------------------------------
?
廣播接收者(BroadcastReceiver)用于接收廣播Intent,廣播Intent的發(fā)送是通過調(diào)用Context.sendBroadcast()、Context.sendOrderedBroadcast()來實現(xiàn)的。通常一個廣播Intent可以被訂閱了此Intent的多個廣播接收者所接收,這個特性跟JMS中的Topic消息接收者類似。要實現(xiàn)一個廣播接收者方法如下:
第一步:繼承BroadcastReceiver,并重寫onReceive()方法。
public?class?IncomingSMSReceiver?extends?BroadcastReceiver?{
@Override?public?void?onReceive(Context?context,?Intent?intent)?{
}
}
第二步:訂閱感興趣的廣播Intent,訂閱方法有兩種:
第一種:使用代碼進行訂閱
IntentFilter?filter?=?new?IntentFilter("android.provider.Telephony.SMS_RECEIVED");
IncomingSMSReceiver?receiver?=?new?IncomingSMSReceiver();
registerReceiver(receiver,?filter);
第二種:在AndroidManifest.xml文件中的<application>節(jié)點里進行訂閱:
<receiver?android:name=".IncomingSMSReceiver">
<intent-filter>
<action?android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
如果你想別人接收到的短信,達到你不可告人的目的,那么使用BroadcastReceiver
當系統(tǒng)收到短信時,會發(fā)出一個廣播Intent,Intent的action名稱為、
如果要短信終止廣播就要配置上你的廣播接收者的級別
<intent-filter?android:priority="100"?>
<action?android:name="android.provider.Telephony.SMS_RECEIVED"?/>
</intent-filter>
android.provider.Telephony.SMS_RECEIVED,該Intent存放了系統(tǒng)接收到的短信內(nèi)容,我們使用名稱“pdus”即可從Intent中獲取到短信內(nèi)容。
在AndroidManifest.xml文件中的<application>節(jié)點里對接收到短信的廣播Intent進行訂閱:
<receiver?android:name=".你的receiver名稱">
<intent-filter><action?android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver>
在AndroidManifest.xml文件中添加以下權限:
<uses-permission?android:name="android.permission.RECEIVE_SMS"/><!--?接收短信權限?-->
<uses-permission?android:name="android.permission.SEND_SMS"/><!--?發(fā)送短信權限?-->
廣播接收者的響應性
在Android中,每次廣播消息到來時都會創(chuàng)建BroadcastReceiver實例并執(zhí)行onReceive()?方法,?onReceive()?方法執(zhí)行完后,BroadcastReceiver?的實例就會被銷毀。當onReceive()?方法在10秒內(nèi)沒有執(zhí)行完畢,Android會認為該程序無響應。所以在BroadcastReceiver里不能做一些比較耗時的操作,否側會彈出ANR(Application?No?Response)錯誤對話框。如果需要完成一項比較耗時的工作,應該通過發(fā)送Intent給Service,由Service來完成。這里不能使用子線程來解決,因為BroadcastReceiver的生命周期很短,子線程可能還沒有結束BroadcastReceiver就先結束了。BroadcastReceiver一旦結束,此時BroadcastReceiver所在的進程很容易在系統(tǒng)需要內(nèi)存時被優(yōu)先殺死,因為它屬于空進程(沒有任何活動組件的進程)。如果它的所在進程被殺死,那么正在工作的子線程也會被殺死。所以采用子線程來解決是不可靠的。
public?class?IncomingSMSReceiver?extends?BroadcastReceiver?{
@Override?public?void?onReceive(Context?context,?Intent?intent)?{
//發(fā)送Intent啟動服務,由服務來完成比較耗時的操作
Intent?service?=?new?Intent(context,?XxxService.class);
context.startService(service);
}
除了短信到來廣播Intent,Android還有很多廣播Intent,如:開機啟動、電池電量變化、時間已經(jīng)改變等廣播Intent。
接收電池電量變化廣播Intent?,在AndroidManifest.xml文件中的<application>節(jié)點里訂閱此Intent:
<receiver?android:name=".IncomingSMSReceiver">
<intent-filter>
<action?android:name="android.intent.action.BATTERY_CHANGED"/>
</intent-filter>
</receiver>
接收開機啟動廣播Intent,在AndroidManifest.xml文件中的<application>節(jié)點里訂閱此Intent:
<receiver?android:name=".IncomingSMSReceiver">
<intent-filter>
<action?android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
并且要進行權限聲明:
<uses-permission?android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
廣播接收者補充
廣播分兩種?
有序廣播?按照廣播的優(yōu)先級?發(fā)給相對應的廣播接收者-1000-1000?激活廣播通過onrecve方法處理
無序廣播
有序廣播有一個特例
sendOrderedBroadcast(intent,?receiverPermission,?resultReceiver,?scheduler,?initialCode,?initialData,?initialExtras);
resultReceiver?廣播接受者?如果我們顯示的指定了廣播接收者?
無論如何?都會接受廣播?無法通過abortBroadcast();的方法終止廣播
比如撥打電話有個out_goingcall?的廣播是指定廣播接收者的無法通過abortBroadcast()方法終止的,但是是可以將撥打的電話號碼數(shù)據(jù)清空置為null,setResultData(null)就無法撥打電話
?
另外一種特殊的廣播sendStickyBroadcast(intent)?//?陰魂不散的廣播?
一般廣播事件發(fā)送完畢被廣播接受者接收到onReceive執(zhí)行完畢后廣播接收者的生命周期就結束了?這個會保持長時間的停留直到廣播事件結束完畢
例如系統(tǒng)的Wifi,網(wǎng)卡狀態(tài)的改變要一定的時間,保證網(wǎng)絡狀態(tài)更新完畢后才結束
代碼中注冊,如果代碼沒有執(zhí)行,就接受不到廣播事件
什么時候使用廣播,例如sdcard新增圖片的時候是無法顯示到圖庫的當sdcard被掛載狀態(tài)發(fā)生改變才會重新加載sdcard的數(shù)據(jù)
這時可以發(fā)送一個sd掛載的通知,通知系統(tǒng)的gallery去獲取到新的圖片.
Intent?intent?=?newIntent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"+Environment.getExternalStorageDirectory()));
sendBroadcast(intent);
總結
以上是生活随笔為你收集整理的android-Service和Thread的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何扩展Linux的ip_conntra
- 下一篇: OpenSSL“心脏出血”漏洞爆发和修复