Activity與Service進行通訊: android
public class MyService extends Service { public static final String TAG = "MyService"; private MyBinder mBinder = new MyBinder(); @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate() executed"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { new Thread(new Runnable() { @Override public void run() { // 開始執行後臺任務 Log.d(TAG, "onStartCommand() executed"); } }).start(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy() executed"); } @Override public IBinder onBind(Intent intent) { return mBinder; } class MyBinder extends Binder { public void startDownload() { new Thread(new Runnable() { @Override public void run() { // 執行具體的下載任務 Log.d(TAG, "startDownload() executed"); } }).start(); } } }
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/start_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Start Service" /> <Button android:id="@+id/stop_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Stop Service" /> <Button android:id="@+id/bind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Bind Service" /> <Button android:id="@+id/unbind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Unbind Service" /> </LinearLayout>
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button startService; private Button stopService; private Button bindService; private Button unbindService; private MyService.MyBinder myBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { //向下轉型 myBinder = (MyService.MyBinder) service; myBinder.startDownload(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startService = (Button) findViewById(R.id.start_service); stopService = (Button) findViewById(R.id.stop_service); bindService = (Button) findViewById(R.id.bind_service); unbindService = (Button) findViewById(R.id.unbind_service); startService.setOnClickListener(this); stopService.setOnClickListener(this); bindService.setOnClickListener(this); unbindService.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.start_service: Intent startIntent = new Intent(this, MyService.class); startService(startIntent); break; case R.id.stop_service: Intent stopIntent = new Intent(this, MyService.class); stopService(stopIntent); break; case R.id.bind_service: Intent bindIntent = new Intent(this, MyService.class); bindService(bindIntent, connection, BIND_AUTO_CREATE); break; case R.id.unbind_service: unbindService(connection); break; default: break; } } }
只有在service與activity沒有關聯,也沒有啓動時,纔會去執行Destroy()方法服務器
簡單來講進行通訊的倆種方式:app
1.BindService():異步
當Activity經過bindService來綁定一個Service時,bindService會當即返回,可是他不會返回Ibinder給客戶端,要接收Ibinder,客戶端Activity必須創建一個長鏈接ServiceConnection 的實例,並傳給bindService(),ServiceConnection 包含一個回調方法來傳遞要返回的IBinderide
2.startService():oop
經過廣播來實現通訊佈局
Thread與Service的區別:ui
Thread是程序執行的最小單位,它是分配CPU的基本單位,能夠用Thread來執行一些異步的操做,是由應用程序託管this
Service是系統的組件,它是由系統進程託管url
Thread的運行時獨立於Activity的,因此所沒有辦法在不一樣的Activity中對同一個Thread進行控制
Service是運行在進程中的主線程中的,而你能夠在任何有Context的地方調用,開啓服務,綁定服務,中止服務,以及接觸綁定來控制它,也能夠在Service裏面註冊廣播,在其餘地方發送廣播來控制它,這些都是Thread作不到的
建立前臺Service:
在Activity的OnCreate()方法中:首先建立一個Notification,而後進行初始化佈局和控件,而後調用startForeground()方法
public class MyService extends Service { public static final String TAG = "MyService"; private MyBinder mBinder = new MyBinder(); @Override public void onCreate() { super.onCreate(); Intent notifyIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent,0); Notification notification = new Notification.Builder(this). setWhen(System.currentTimeMillis()). setAutoCancel(false). setSmallIcon(R.mipmap.ic_launcher). setContentTitle("通知"). setContentText("我是服務的通知"). setContentIntent(pendingIntent). setDefaults(Notification.DEFAULT_ALL). // 設置用手機默認的震動或聲音來提示 build(); // 設置爲前臺服務,在系統狀態欄顯示 startForeground(1, notification); } }
Service的優先級:
經過startForeground(true)來設置Service的優先級,默認啓動的Service是被標記爲background,也就是說設置foreground,那麼他就和正在運行的Activity優先級獲得了必定得提升
如何保證Service不被殺死:
1.提高Service的優先級
2.在onDestory()中從新啓動服務
3.監聽系統廣播判斷Service狀態
經過系統的一些廣播,好比:手機重啓、界面喚醒、應用狀態改變等等監聽並捕獲到,而後判斷咱們的Service是否還存活
4.雙進程Service
讓2個進程互相保護,其中一個Service被清理後,另外沒被清理的進程能夠當即重啓進程
5.用戶不干預,徹底靠系統來控制,辦法有不少。好比onStartCommand()方法的返回值設爲START_STICKY
,服務就會在資源緊張的時候被殺掉,而後在資源足夠的時候再恢復。固然也可設置爲前臺服務,使其有高的優先級,在資源緊張的時候也不會被殺掉
6.守護進程:
守護進程通常在系統啓動時開始運行,除非強行終止,不然直到系統關機都保持運行
守護進程(Daemon Process),也就是一般說的 Daemon 進程(精靈進程),是 Linux 中的後臺服務進程。它是一個生存期較長的進程,一般獨立於控制終端而且週期性地執行某種任務或等待處理某些發生的事件。
守護進程是個特殊的孤兒進程,這種進程脫離終端,爲何要脫離終端呢?之因此脫離於終端是爲了不進程被任何終端所產生的信息所打斷,其在執行過程當中的信息也不在任何終端上顯示。因爲在 Linux 中,每個系統與用戶進行交流的界面稱爲終端,每個今後終端開始運行的進程都會依附於這個終端,這個終端就稱爲這些進程的控制終端,當控制終端被關閉時,相應的進程都會自動關閉。
Linux 的大多數服務器就是用守護進程實現的。好比,Internet 服務器 inetd,Web 服務器 httpd 等
IntentService
IntentService是繼承並處理異步請求的一個類,在IntentService內有一個工做線程來處理耗時操做,啓動IntentService的方式和啓動傳統的Service同樣,同時,當任務執行完後,IntentService會自動中止,而不須要咱們手動去控制或stopSelf()。另外,能夠啓動IntentService屢次,而每個耗時操做會以工做隊列的方式在IntentService的onHandleIntent回調方法中執行,而且,每次只會執行一個工做線程,執行完第一個再執行第二個,以此類推。
package com.example.service; import android.app.IntentService; import android.content.Intent; import android.os.Looper; import android.support.annotation.Nullable; import android.util.Log; /** * Created by 郝悅 on 2018/1/30. */ public class MyIntentService extends IntentService { public static final String TAG ="MyIntentService"; /** * Creates an IntentService. Invoked by your subclass's constructor. * */ public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(@Nullable Intent intent) { // 這裏已是工做線程,在這裏執行操做就行 boolean isMainThread = Thread.currentThread() == Looper.getMainLooper().getThread(); Log.i(TAG,"is main thread:"+isMainThread); // 執行耗時下載操做 mockDownload(); } /** * 模擬執行下載 */ private void mockDownload(){ try { Thread.sleep(5000); Log.i(TAG,"下載完成..."); }catch (Exception e){ e.printStackTrace(); } } }
判斷了是否爲主線程,結果爲false ,說明是開啓了一個工做線程,5s 以後,打印了下載完成,而且自動中止了服務。
特色:
1.建立了一個獨立的工做線程來處理全部的經過onStartCommand()傳遞給服務的intents
2.建立一個工做隊列,來逐個發送intent給onHandlerIntent()
3.不須要主動調用stopSelft()來結束服務
4.默認實現的onBind()返回null
5.默認實現的onStartCommand()的目的是將intent插入到工做隊列中,由於在全部的intent被處理完後,系統會自動關閉服務
IntentService
本質 = Handler
+ HandlerThread
:
HandlerThread
單獨開啓1個工做線程:IntentService
Handler
:ServiceHandler
ServiceHandler
與 IntentService
onStartCommand()
傳遞服務intent
到ServiceHandler
、依次插入Intent
到工做隊列中 & 逐個發送給 onHandleIntent()
onHandleIntent()
依次處理全部Intent
對象所對應的任務