Android中 service組件詳解
service組件跟activity組件及其類似,可以說(shuō)service是沒(méi)有界面的activity,
當(dāng)然service的生命周期和activity還是有一定的差別的。
service組件一般用在什么地方的,上面講了service組件沒(méi)有界面,不用跟用戶直接交互,
所以service組件一般運(yùn)行在后臺(tái)。比如做一些不需要界面的數(shù)據(jù)處理等等。
開(kāi)發(fā)service需要兩個(gè)步驟:
1,定義一個(gè)基礎(chǔ)service的子類。
2,在AndroidManifest.xml 文件中配置該service。
怎么啟動(dòng)service呢,想想啟動(dòng)activity是不是有兩種方法:
startActivity(intent),
startActivityForResult(intent)
那么啟動(dòng)service也有兩種方法:
startService(intent),
bindService(Intent service,ServiceConnection conn,int flags),
兩者有什么區(qū)別可以先看下面的代碼:
public class BindService extends Service { private int count; private boolean quit; // 定義onBinder方法所返回的對(duì)象 private MyBinder binder = new MyBinder(); // 通過(guò)繼承Binder來(lái)實(shí)現(xiàn)IBinder類 public class MyBinder extends Binder { public int getCount() { // 獲取Service的運(yùn)行狀態(tài):count return count; } } // 必須實(shí)現(xiàn)的方法 @Override public IBinder onBind(Intent intent) { System.out.println("Service is Binded"); // 返回IBinder對(duì)象 return binder; } // Service被創(chuàng)建時(shí)回調(diào)該方法。 @Override public void onCreate() { super.onCreate(); System.out.println("Service is Created"); // 啟動(dòng)一條線程、動(dòng)態(tài)地修改count狀態(tài)值 new Thread() { @Override public void run() { while (!quit) { try { Thread.sleep(1000); } catch (InterruptedException e) { } count++; } } }.start(); } // Service被斷開(kāi)連接時(shí)回調(diào)該方法 @Override public boolean onUnbind(Intent intent) { System.out.println("Service is Unbinded"); return true; } // Service被關(guān)閉之前回調(diào)。 @Override public void onDestroy() { super.onDestroy(); this.quit = true; System.out.println("Service is Destroyed"); } @Override public void onRebind(Intent intent) { super.onRebind(intent); this.quit = true; System.out.println("Service is ReBinded"); } }
上面的Service的作用是 簡(jiǎn)單的開(kāi)啟一個(gè)線程,每 1秒鐘 count++,這個(gè)count數(shù)據(jù)
通過(guò) binder對(duì)象 傳遞給 訪問(wèn)者。
待會(huì)再做詳解,先看下面的代碼怎么啟動(dòng)Service,并得到 Service的 count數(shù)據(jù)
public class MainActivity extends Activity { Button startService_bnt , bindService_bnt; // 保持所啟動(dòng)的Service的IBinder對(duì)象 BindService.MyBinder binder; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); startService_bnt = (Button) findViewById(R.id.start_bnt); bindService_bnt = (Button) findViewById(R.id.bind_bnt); //創(chuàng)建啟動(dòng)Service的Intent Intent intent = new Intent(this,BindService.class); startService_bnt.setOnClickListener(new OnClickListener() { @Override public void onClick(View source) { //綁定指定Serivce startService(intent); } }); bindService_bnt.setOnClickListener(new OnClickListener() { @Override public void onClick(View source) { //綁定指定Serivce bindService(intent , conn , Service.BIND_AUTO_CREATE); Toast.makeText(MainActivity.this , "Serivce的count值為:" + binder.getCount() , 4000) .show(); } }); } // 定義一個(gè)ServiceConnection對(duì)象 private ServiceConnection conn = new ServiceConnection() { // 當(dāng)該Activity與Service連接成功時(shí)回調(diào)該方法 @Override public void onServiceConnected(ComponentName name , IBinder service) { System.out.println("--Service Connected--"); // 獲取Service的onBind方法所返回的MyBinder對(duì)象 binder = (BindService.MyBinder) service; } // 當(dāng)該Activity與Service斷開(kāi)連接時(shí)回調(diào)該方法 @Override public void onServiceDisconnected(ComponentName name) { System.out.println("--Service Disconnected--"); } }; }
上面activity定義了兩個(gè)按鈕,點(diǎn)擊兩個(gè)按鈕有兩種不同的方法啟動(dòng)Service:
startService(intent), bindService(Intent service,ServiceConnection conn,int flags),
現(xiàn)在來(lái)講解一下兩種啟動(dòng)方式的區(qū)別,并解釋上面的代碼。
startService(intent)
啟動(dòng)Service呢它不具有與訪問(wèn)者交互的能力,就像activity 的 startActivity(),
它不能從新啟動(dòng)的activity拿到返回?cái)?shù)據(jù)一樣
而bindService(Intent service,ServiceConnection conn,int flags),就不一樣了
訪問(wèn)者能從啟動(dòng)的Service 拿到數(shù)據(jù),怎么拿到的呢,bindService的第二個(gè)參數(shù) conn,該參數(shù)是一個(gè) ServiceConnection 對(duì)象,當(dāng)訪問(wèn)者與Service連接成功 就會(huì)回調(diào)ServiceConnection 的 onServiceConnected() 方法 ,上面的程序就是在這個(gè)回調(diào)方法里面拿到 IBinder 對(duì)象的。
可以在看一下
// 定義一個(gè)ServiceConnection對(duì)象 private ServiceConnection conn = new ServiceConnection() { // 當(dāng)該Activity與Service連接成功時(shí)回調(diào)該方法 @Override public void onServiceConnected(ComponentName name , IBinder service) { System.out.println("--Service Connected--"); // 獲取Service的onBind方法所返回的MyBinder對(duì)象 binder = (BindService.MyBinder) service; } // 當(dāng)該Activity與Service斷開(kāi)連接時(shí)回調(diào)該方法 @Override public void onServiceDisconnected(ComponentName name) { System.out.println("--Service Disconnected--"); } };
簡(jiǎn)單點(diǎn)也就是說(shuō) 訪問(wèn)者通過(guò) bindService 綁定到 Service,綁定成功后會(huì)回調(diào)ServiceConnection 中的 onServiceConnected()方法,這個(gè)方法里面有IBinder service 參數(shù),這個(gè)參數(shù)就是 Service暴露給 訪問(wèn)者的對(duì)象,訪問(wèn)者拿到這個(gè)對(duì)象就可以訪問(wèn) Service的數(shù)據(jù)了
這就是 訪問(wèn)者與Service數(shù)據(jù)交互的原理,是通過(guò) IBinder 對(duì)象來(lái)傳遞的。
可能到這這里你還對(duì) binder = (BindService.MyBinder) service;這句代碼不理解。
你肯能覺(jué)得 拿到的IBinder 對(duì)象不應(yīng)該是上面Service代碼中onBind 方法返回的 binder 才是嘛,怎么 強(qiáng)轉(zhuǎn)成 BindService.MyBinder 對(duì)象了。
而且返回的 binder 也沒(méi) count數(shù)據(jù),訪問(wèn)者怎么就能 binder.getCount() 得到數(shù)據(jù)呢。
@Override public IBinder onBind(Intent intent) { System.out.println("Service is Binded"); // 返回IBinder對(duì)象 return binder; }
別忘了 上面Service代碼里面還對(duì) IBinder 對(duì)象進(jìn)行處理
// 通過(guò)繼承Binder來(lái)實(shí)現(xiàn)IBinder類 public class MyBinder extends Binder { public int getCount() { // 獲取Service的運(yùn)行狀態(tài):count return count; } }
Binder 是 IBinder 的 實(shí)現(xiàn)類,MyBinder 繼承Binder 并在里面定義了個(gè)方法。
那么 拿到 IBinder 對(duì)象 就相當(dāng)于 拿到 MyBinder 對(duì)象,就可以訪問(wèn) getCount方法了,這也是 為什么 binder = (BindService.MyBinder) service; 進(jìn)行強(qiáng)轉(zhuǎn),并且binder.getCount() 可以拿到 count 數(shù)據(jù),因?yàn)?IBinder 里面并沒(méi)有業(yè)務(wù)實(shí)現(xiàn),是MyBinder 幫它實(shí)現(xiàn)了。
- 淺談Service Manager成為Android進(jìn)程間通信(IPC)機(jī)制Binder守護(hù)進(jìn)程之路
- Android Service判斷設(shè)備聯(lián)網(wǎng)狀態(tài)詳解
- Android AIDL和遠(yuǎn)程Service調(diào)用示例代碼
- Android Service詳解及示例代碼
- Android基于Service的音樂(lè)播放器
- Android IPC機(jī)制綁定Service實(shí)現(xiàn)本地通信
- Android實(shí)現(xiàn)開(kāi)機(jī)自動(dòng)啟動(dòng)Service或app的方法
- Android使用Messenger實(shí)現(xiàn)service與activity交互
- Android Service總結(jié)及詳細(xì)介紹
相關(guān)文章
Android ListView下拉刷新上拉自動(dòng)加載更多DEMO示例
這篇文章主要介紹了Android ListView下拉刷新上拉自動(dòng)加載更多DEMO示例的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07Android自定義ViewGroup實(shí)現(xiàn)可滾動(dòng)的橫向布局(2)
這篇文章主要介紹了Android自定義ViewGroup實(shí)現(xiàn)可滾動(dòng)的橫向布局,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12Android實(shí)現(xiàn)九宮格(GridView中各項(xiàng)平分空間)的方法
這篇文章主要介紹了Android實(shí)現(xiàn)九宮格(GridView中各項(xiàng)平分空間)的方法,涉及Android針對(duì)GridView操作的相關(guān)技巧,需要的朋友可以參考下2015-06-06Android 開(kāi)發(fā)隱藏標(biāo)題欄的方法總結(jié)
這篇文章主要介紹了android 開(kāi)發(fā)隱藏標(biāo)題欄的方法總結(jié)的相關(guān)資料,需要的朋友可以參考下2017-04-04Android仿正點(diǎn)鬧鐘時(shí)間齒輪滑動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Android仿正點(diǎn)鬧鐘時(shí)間齒輪滑動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01Android中Glide加載到RelativeLayout背景圖方法示例
Glide框架大家應(yīng)該都很熟悉,我們可以使用Glide加載網(wǎng)絡(luò)圖片、加載gif圖片,使用簡(jiǎn)單。下面這篇文章主要給大家介紹了關(guān)于Android中Glide加載到RelativeLayout背景圖的相關(guān)資料,需要的朋友可以參考下。2017-12-12Flutter實(shí)現(xiàn)仿京東商品詳情底部操作欄
這篇文章主要為大家詳細(xì)介紹了Flutter如何仿京東實(shí)現(xiàn)商品詳情底部操作欄,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2023-06-06