android基礎之Service
一:Service的概述
Service是Android四大基本組件(Service,Activity,Context Provider,BroadcastReceiver它們之間依靠Intent建立聯繫)中與Activity最相似的組件。都代表 執 行的程序,Service與Activity的區別在於:
Service一直在後臺運行,它沒有用戶界面,所以絕不會到前臺 來。一旦Service被啓動起來之後,它就與Activity一樣。完全具有自己的生命週期。
關於程序中Activity和service的選擇標準:
如果某個程序組件需要在運行時向用戶呈現某種界面,或者該程序需要與用戶交互,就需要使用Activity,否則就應該考慮使用Service了。
如:下載東西,播放音樂。可以一邊下載,一邊播放,一邊玩其他的事情。但是Activity是無法做到的。只要Activity被關閉或者最小化了,程序就停止了。
二:特點
1.沒有UI
2.進行耗時較長或者與用戶沒有交互的一些功能
3.Service具有較高的優先級,比stop的Activity優先級要高,最高的優先級是前臺Activity
4.具有較長的生命週期
三.使用
看到這裏你也許會問爲什麼Service會有2中生命週期呢。哈哈,
其實這是跟Service的使用方式有關的。Service有2中不同的使用方式。
我們先創建一個android application project工程,然後在默認包下新建一個class,取名爲firstService 繼承Service如圖:
既然Service是我們自定義的,當然我們要在清單文件裏面註冊一下。(在AndroidManifest.xml的 <application>標籤加入如下內容):
name裏面放的是類的包名+類名,一般會有提示。
第一種使用方式(對應最左邊的圖)
這裏我在主界面放了個按鈕,然後設置的android:onClick="btn2"
這種方式啓動的Service,並沒有將之與Activity綁定,所以作爲一個單獨存在的實體,本身的生命週期不受別人影響。也沒有辦法與其他組件之間進行數據交互。
就像我們電腦的一些一些系統服務一樣,很多時候我們是通過強制手段關閉的。
第二種方式,對應最右邊的圖。
通常情況下,我們希望一個後臺的Service是可控的,同時用戶也希望知道這個服務的運行狀態,就拿下載東西來說,有的時候用戶希望看到實時的數據變化。第一種方式在這種情況下顯然不能滿足我們的需求,畢竟大多數場景下,用戶希望服務受自己掌控,同時靈活的數據是app的靈魂。
我們知道,service沒有ui所以要通過Activity提供ui。第二種方式就是通過activity與service的綁定實現的。用同樣的方式,我們在佈局裏面再放一個按鈕,然後設置的android:onClick="btn1"在activity的主函數裏面定義按鈕點擊事件。
前面都差不多。就啓動時用
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
啓動。原理都說的差不多了。建議寫代碼時對着生命週期來寫。
package com.example.mydemo;
import com.example.mydemo.secondService.mybinder;
import android.app.Activity;
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.widget.Toast;
public class MainActivity extends Activity {
private mybinder mybinder;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
//當訪問者與之連接成功時調用
@Override
public void onServiceConnected(ComponentName name, IBinder ibinder) {
// TODO Auto-generated method stub
mybinder = (com.example.mydemo.secondService.mybinder) ibinder;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* startService所啓動的服務
* 1.它是不受任何人影響的
* 2.它是作爲一個單獨的個體存在的,沒有辦法與其他組件之間進行數據交互
* @param view
*/
public void btn(View view){
Toast.makeText(MainActivity.this, mybinder.getCount()+"", Toast.LENGTH_LONG).show();
}
public void btn1(View view){
unbindService(serviceConnection);
}
public void btn2(View view){
Intent intent = new Intent(this,secondService.class);
// startService(intent);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
/**
* 如果使用bindServiuce啓動的服務,那麼service就與調用者的生命週期就有關聯了,
* 所以退出時也要終止service
*/
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
unbindService(serviceConnection);
super.onDestroy();
}
}
創建2個service自己隨便取名字,別忘了在清單文件註冊就是。
第一個service對應第一種啓動方式:
package com.example.mydemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class firstService extends Service {
final String tag = "firstService";
boolean flag = true;//邏輯控制開關
int count=0;//測試參數
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onCreate()");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onStartCommand()");
new Thread(){
public void run() {
while(flag){
System.out.println("進度:"+count++);
if(count>99){
flag=false;
}
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();;
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onDestroy()");
flag = false;
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
第一個service對應第二種啓動方式:
package com.example.mydemo;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class secondService extends Service{
boolean flag = true;
final String tag = "secondService";
int count=0;
class mybinder extends Binder{
public int getCount(){
return count;
}
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onCreate()");
super.onCreate();
}
//建立契約
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onBind()");
new Thread(){
public void run() {
while(flag){
System.out.println("進度:"+count++);
if(count>100){
flag=false;
}
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
return new mybinder();
}
//解除契約
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onUnbind()");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
flag = false;
Log.i(tag, tag+"....onDestroy()");
super.onDestroy();
}
}
activity的主函數調用
package com.example.mydemo;
import com.example.mydemo.secondService.mybinder;
import android.app.Activity;
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.widget.Toast;
public class MainActivity extends Activity {
private mybinder mybinder;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
//當訪問者與之連接成功時調用
@Override
public void onServiceConnected(ComponentName name, IBinder ibinder) {
// TODO Auto-generated method stub
mybinder = (com.example.mydemo.secondService.mybinder) ibinder;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* startService所啓動的服務
* 1.它是不受任何人影響的
* 2.它是作爲一個單獨的個體存在的,沒有辦法與其他組件之間進行數據交互
* @param view
*/
public void btn(View view){
Toast.makeText(MainActivity.this, mybinder.getCount()+"", Toast.LENGTH_LONG).show();
}
public void btn1(View view){
unbindService(serviceConnection);
}
public void btn2(View view){
Intent intent = new Intent(this,secondService.class);
// startService(intent);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
/**
* 如果使用bindServiuce啓動的服務,那麼service就與調用者的生命週期就有關聯了,
* 所以退出時也要終止service
*/
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
unbindService(serviceConnection);
super.onDestroy();
}
}
效果就不發了。反正第二種方式所打開的service它的生命週期已經和activity綁定了。
這種方式可以讓我們自定義地暫停和重啓服務。