1、Service與Activity相同與不同
2、Service組件創建步驟
3、Service組件生命週期方法
4、Service組件兩種運行方式
5、Service組件與調用者的通訊方式Binder和IBinder區別和用法
———————————–1、service與Activity的相同與不同——————————————
相同點:都是從Context上派生出來的,可以調用context的getResoutces()和getContextResolver
()等方法。他們都代表可執行的程序,都有不同的生命週期,不同的生命週期回調相應的方法。實現方式相似,子類繼承他們,重載不同生命週期的相應方法就可以實現業務邏輯。創建方式上都是需要再manifest中進行註冊。對應耗時任務,都不建議在主進程中進行,而是開闢新的進程來處理。
不同點:Service代表後臺程序,在後臺運行,沒有用戶界面,不出現在前臺。啓動方式上,安卓5.0以上要求Activity必須顯示啓動Service。
如何選擇Service和Activity:當一個程序需要和用戶交互,或者呈現想要的界面給用戶,那麼就用Activity,否則就用Service。
————————————–2、Service的創建步驟—————————————–
創建步驟:
首先定義一個繼承Service的子類(這裏需要添加不同生命週期的方法,詳細見下面的實例)
在AndroidManifest.xml中配置,以< service android:name=”xxx”>< /service>進行
———————————–3、Service的生命週期方法————————————
1、必須實現的方法IBinder onBind(Intent intent),注意該方法如果不需要與調用者進行通訊,則return null;如果需要與調用者通訊,那麼則要返回一個IBinder對象,這個對象可以通過內部類的方式來實現,具體表現方式見兩種創建方式中的第二個;
2、void onCreate()方法,它表示該Service第一次創建的時候立刻回調,有點類似Activity;注意他只執行一次;
3、void onDestroy()方法,它表示該Service被關閉之前調用,如果斷開連接的時候也回調該方法(第二種啓動方式);
4、void onStartCommandr(Intent intent,int flags,int startId)方法,該方法是每次Service被調用的時候回調它,與onCreate()的區別在於,onCreate()只是在第一次建立的時候回調,但是這個void onStartCommand(Intent intent,int flags,int startId)它每次都湊熱鬧啓動。
5、boolean onUnbind(Intent intent)方法,當Service上綁定的所有客戶端都斷開連接的時候回調它,我們也可以主動斷開Service,那麼就用到它了,主動斷開,注意主動斷開Service的時候,ServiceConnection 中的onServiceDisconnected方法將不會回調。
示例:
————————4、Service的兩種運行方式———————————–
方式一:通過Context的StartService()和stopService()來運行,該方法啓動的Service和調用者並沒有半毛錢關係,當調用者退出了,Service繼續運行。
寫多了累,上圖!
這個實例就是簡單的啓動和關閉服務,沒有什麼其他的,只是調用的Activity關閉了,Service繼續運行。
方式二:通過Context的bindService()方法啓動,重點來了,使用該方法調用者與Service有着綁定關係,訪問者一旦退出,Service也就終止了。下面詳細講解第二種運行方式及如何通過IBinder對象進行通訊的,下面的內容默認爲第二種運行方式:
——————————–小強來了——————————
運行此種方法的原因:
由於第一種方式調用者與Service雖然有啓動關係,但是啓動之後他們之間就沒有任何關係,所以當需要調用者與被啓動的Service需要數據傳輸或者通訊的時候,就需要我們的bindService()來解決了;
此種方法全名和參數詳解:
bindService(Intent service,ServiceConnection conn,int flags)
參數Intent service:建立一個意圖,明確我們需要啓動那個Service,如Intent intent = new Intent(this,BindService.class);
參數ServiceConnection conn: 是個ServiceConnection對象,他用於監聽訪問者與需要啓動的 Service是否建立聯繫,
如果連接成功則回調方法:ServiceConnection.onServiceConnected(ComponentName name**,IBinder service)**;
如果斷開連接則回調方法:ServiceConnection.onServiceDisConnected(ComponentName name,IBinder service);
注意:這裏的斷開連接是系統自動斷開的,如果是我們自己主動斷開的,則不調用ServiceConnection.onServiceDisConnected(ComponenetName name,IBinder service);
參數:flags看着名字也知道是什麼意思,這裏分爲自動創建和不自動創建,自動創建爲BIND_AUTO_CREATE;不自動創建爲0;
上代碼:service代碼
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class MyService extends Service {
private int count;
private boolean quit;
private MyBinder binder = new MyBinder();
public class MyBinder extends Binder{
public int getCount(){
return count;
}
}
/*
* IBinder和Binder的關係:
* 1.IBinder是接口,Binder是具體實現類,實現了IBinder的類需要重載編寫行爲和邏輯,而Binder是具體類,具有自己的功能。
* 2.一個繼承了Binder的類就實現了一個IBinder接口.Binder是IBinder的實現類;
*/
//必須實現的方法
@Override
public IBinder onBind(Intent intent) {
System.out.println("Service is Binder!");
return binder;
}
//當創建Service時調用
@Override
public void onCreate() {
super.onCreate();
System.out.println("Service is Create!");
new Thread(){
@Override
public void run(){
while(!quit){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
}
count++;
}
}
}.start();
}
//當被斷開連接的時候調用該方法
@Override
public boolean onUnbind(Intent intent) {
System.out.println("Service is unConnection!");
return true;
}
//當關閉Service的之前調用該方法
@Override
public void onDestroy() {
super.onDestroy();
this.quit = true;
System.out.println("Service is Destroy!");
}
}
上代碼:Activity代碼:
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
/*
* 創建ServiceConnection對象,關於ServiceConnection的詳細理解隨後查閱
* 當創建ServiceConnection之後,必須要重載他的兩個方法,
* 一個是建立連接的時候調用的onServiceConnected(ComponenetName name,iBinder service);
* 一個是斷開連接的時候調用的onServiceDisConneced(ComponentName name);
*
*
*/
private MyService.MyBinder binder;
private Button create,unBind,get;
private ServiceConnection conn = new ServiceConnection(){
//當該Activity與Service建立連接的時候回調該方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("--Service connection---!");
binder = (MyService.MyBinder)service;
}
//當該Activity與Service斷開連接的時候回調該方法
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("Server Disconnection");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
create = (Button)findViewById(R.id.create);
unBind = (Button)findViewById(R.id.unbind);
get = (Button)findViewById(R.id.get);
final Intent intent = new Intent(this,MyService.class);//創建啓動Service的Intent
create.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View resources){
bindService(intent,conn,Service.BIND_AUTO_CREATE);
}
});
unBind.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View resources){
unbindService(conn);
}
});
get.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View resources){
Toast.makeText(MainActivity.this,String.valueOf(binder.getCount()), Toast.LENGTH_LONG).show();
}
});
}
}
這裏重點說下用bindService(intent,conn,flags)運行的程序如何在調用者和Service頁面傳遞數據的:
首先是方法bindService(Intent intent,ServiceConnection conn,int flags) 啓動了程序。
啓動程序後Service的onCreate()開始運行,丟丟丟丟丟……..開始運行了。
然後運行onBind()方法了,create之後就能確認綁定了,這個方法的回調條件是確認Service綁定,這裏需要注意了,重點來了:這裏我們return binder;了,這個binder是繼承了Binder的內部類的實例化,代碼在這兩行:
private MyBinder binder = new MyBinder();
public class MyBinder extends Binder{
public int getCount(){
return count;
}
}
然後開始回調方法onServiceConnected(ComponentName name,IBinder service了,該方法回調條件就是建立連接。這裏的service是IBinder類型,她(注意有一個美女的她來表示)等於前面方法onBind()方法return binder,她接受了return的結果,因爲不是大腿,不是老司機,所以不知道底層怎麼傳輸的,這裏我就記住吧,這裏的service就是前面繼承了IBinder的內部類的實例化,實際上通過這個繼承了IBinder的內部類實例化,我們可以調用很多Service裏面的東西,只要需要!下面應用書上的一段話來總結,加深下印象:
IBinder對象相當於Service組件的內部鉤子,該鉤子關聯到綁定的Service組件,當其他程序組件綁定了該Service時,Service將把Ibinder對象返回給其他程序組件,其他程序組件通過Ibinder對象即可進行實施通信!
還有一段哈,是這樣說的:
對於Service的onBind()方法返回的IBinder對象來說,他可以被當成該Service組件所返回的代理對象,Service允許調用者通過該IBinder對象來訪問Service內部數據,這樣就可以實現調用者或者客戶端與Service之間的數據傳輸
對於Service頁面中利用繼承了Binder的內部類實例化對象來返回給調用者,書上說是通用的做法,那就記住吧,小白的我也不知道其他辦法,說實話我都不知道怎麼用,先記住吧。