標籤:pat 建立 四大組件 string false anr 解決問題 span ace
原創文章,轉載請註明 http://blog.csdn.net/leejizhou/article/details/50866875 李濟洲的部落格
Service是Android四大組件之中的一個。Service主要作用於後台,能夠進行一些背景操作,它沒實使用者介面。它跟Activity比較類似,某種意義上能夠理解為“Service是沒實使用者介面的Activity“,那麼我們什麼時候須要使用Service呢?比如:音樂App現正播放音樂我們想切換到閱讀App又不想讓音樂停止就會用到Service,音樂App正在下載音樂我們切換到案頭又不想讓下載停止就會使用到Service。
編寫Activity須要兩步:1:編寫Activity的子類 2:在AndroidManifest.xml中配置此Activity,相同編寫Service也須要兩步:
1:定義一個繼承自Service的子類
2:在AndroidManifest.xml中配置此Service
startService
我們先編寫一個簡單的StartService示範範例程式來示範怎樣實現Android後台操作
先定義一個Service的子類,然後複寫一些生命週期函數
/** * Blog:http://blog.csdn.net/leejizhou * 李濟洲的部落格 */public class MyService extends Service { //Service中唯一的抽象方法。必須在子類中實現,用來和Activity通訊。先返回NULL @Nullable @Override public IBinder onBind(Intent intent) { return null; } //複寫Service的一些生命週期函數 //onCreate會在Service第一次建立的時候調用 @Override public void onCreate() { super.onCreate(); Log.d("MyService","----onCreate executed----"); } //onStartCommand會在Service每次啟動的時候調用 @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("MyService","----onStartCommand----"); return super.onStartCommand(intent, flags, startId); } //onDestroy會在Service銷毀時候調用 @Override public void onDestroy() { super.onDestroy(); Log.d("MyService", "----onDestroy----"); }}
以下是Service的生命週期,為什麼有兩種呢?由於啟動Servcie有兩種方式第一個是startService()主要用於啟動一個Service運行背景工作不進行通訊,還有一個是bindService()是啟動一個跟組件綁定的Service能夠進行通訊,先介紹的是startService()。
然後在AndroidManifest.xml中進行配置此Service。千萬不要忘記。
<service android:name=".MyService"></service>
定義好Service後,接下來就是啟動和停止這個服務了。啟動和停止主要靠Intent來實現,這裡我定義了兩個Button用來啟動和停止。部分代碼略(文章結尾會提供原始碼),主要看下啟動和停止Service的實現代碼。
//開啟Service findViewById(R.id.StartService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(MainActivity.this,MyService.class); startService(intent); } }); //停止Service findViewById(R.id.StopService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(MainActivity.this,MyService.class); stopService(intent); } });
點擊開啟Service能夠看到OnCreate和OnStartCommand被運行了,一個簡單的後台Service就被啟動了
然後點擊停止。能夠看到OnDestroy被運行了
這裡可能你會問了。啟動Service,OnCreate和OnStartCommand都被運行了,他倆有什麼差別呢?onCreate會在Service第一次建立的時候調用,假設一個Service沒有Stop再次啟動這個Service的話是不會再調用onCreate方法了,可是每次OnStartCommand都會被調用。所以後台須要啟動並執行代碼邏輯我們一般須要放到OnStartCommand方法裡面。
Ok 在Activity裡面啟動一個簡單的Service後台服務就完畢了,可是你要知道的是通過startService()啟動這個服務後就和Activity就沒有關係了,即使你這個Activity被銷毀這個Service依舊會在後台運行。切記通過startService()啟動服務任務結束後在Activity中調用 stopService()結束掉這個Service。或者在Servcie子類中調用stopSelf()來結束自己。
上面介紹了startService啟動服務,它能夠很簡單的啟動後台Service進行一些邏輯操作,可是無法進行控制和通訊,以下介紹下BindService能夠解決問題。
bindService
以下實現一個後台Service進行數值的遞增運算。Activity能夠即時查看Service此時的數值的小示範範例來瞭解bindService的使用。
定義Service。這裡我們要實現onBind的方法。在這裡onStartCommand無需複寫,由於通過bindService啟動服務是不回調此方法的。Service的onCreate裡面進行的了一個迴圈的數值運算。
/** * Blog:http://blog.csdn.net/leejizhou * 李濟洲的部落格 */public class MyService extends Service { //當前數值 private int num=0; //是否停止迴圈 private boolean isgo=true; //BindService 須要實現onBind方法 自己定義一個Binder對象返回 private MyBinder binder=new MyBinder(); @Nullable @Override public IBinder onBind(Intent intent) { return binder; } public class MyBinder extends Binder{ //建立一個方法用於返回當前數值 public int getNum(){ return num; } } //Service建立時候回調此方法 這裡定義一個迴圈 不斷更改num的值 @Override public void onCreate() { super.onCreate(); //進行迴圈操作,每秒數值加1 new Thread(new Runnable() { @Override public void run() { while(isgo){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } num++; Log.i("MyService",num+""); } } }).start(); } //這裡不須要複寫此方法。由於bindService啟動服務不會調用此方法// @Override// public int onStartCommand(Intent intent, int flags, int startId) {// return super.onStartCommand(intent, flags, startId);// } //Service斷開時回調此方法 @Override public boolean onUnbind(Intent intent) { Log.i("MyService","----onUnbind----"); return super.onUnbind(intent); } //Service銷毀是回調此方法 @Override public void onDestroy() { super.onDestroy(); isgo=false; Log.i("MyService","----onDestroy----"); }}
然後再AndroidManifest.xml中佈建服務,一定一定一定不要忘記。
<service android:name=".MyService"></service>
之後在Activity裡面通過bindService啟動服務,Activity裡面三個button用來啟動 停止 和擷取數值
/** * Blog:http://blog.csdn.net/leejizhou * 李濟洲的部落格 */public class MainActivity extends AppCompatActivity { //擷取Service中的Binder對象 MyService.MyBinder binder; //定義一個ServiceConnection對象 private ServiceConnection connection=new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { //Activity與Service串連成功時候回調此方法 binder=(MyService.MyBinder)service; } @Override public void onServiceDisconnected(ComponentName name) { //Activity與Service中斷連線時回調此方法,Activity主動調用unBindService將不掉用此方法。僅僅在異常終止時刻調用 Log.i("MyService","----onServiceDisconnected-----"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //啟動Service findViewById(R.id.bindService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent bindIntent=new Intent(MainActivity.this, MyService.class); //這裡第一個參數傳入intent 第二個參數傳入ServiceConnection對象 //第三個參數指Activity和Service綁定時是否建立服務。這裡直接傳BIND_AUTO_CREATE就好了。之後Service的onCreate會得到運行 bindService(bindIntent,connection, Service.BIND_AUTO_CREATE); } }); //停止Service findViewById(R.id.UnBindService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //解除綁定Service unbindService(connection); } }); //擷取Service中此刻的數值 findViewById(R.id.getnum).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this,"Service的數值"+binder.getNum()+"",3000).show(); } }); }}
bindService運行生命週期
注意到Activity中ServiceConnection對象中的OnServiceConnected方法中有一個IBinder對象,該對象就可以實現Activity與Service之間的通訊,使用bindService方式啟動Service的時候,Service子類必須實現onBind方法,onBind方法返回的IBinder對象將會傳遞到onServiceConnected(ComponentName name, IBinder service)其中來實現通訊互動。
這樣Activity和Service通訊的小示範範例就完畢了,值得注意的是通過onBind方法啟動Service,Service和Activity是綁定狀態的。那麼假設Activity被銷毀Service也會跟著一起銷毀這點要注意,要區分startService和bindService的差別。
那麼你可能會問假設我想讓Service能夠和Activity通訊同一時候又能夠不隨Activity銷毀該怎樣做呢?僅僅須要 startService和bindService一起調用就能夠了。假設同一時候調用了start和bind,那麼調用unbindService將不會停止Service,而必須調用 stopService 或 Service的 stopSelf 來停止服務。
在使用Service中有一個誤區會有人以為在Service中的onCreate中能夠進行耗時操作。這是不正確的,Service依舊是運行在主線程中的,假設直接進行耗時操作很easy造成ANR,所以即使在Service中耗時操作依舊要放到子線程其中。
最後總結下什麼情況下使用startService或bindService呢。假設你僅僅想啟動一個後台服務去運行一個某項長期任務的話使用startService就能夠了。假設你想要與正在啟動並執行後台Service取得聯絡的話能夠使用bindService,假設想要Service長期運行不隨Activity銷毀而且能夠進行通訊那麼就調用了startService後再調用bindService。Service的總結先告一段落。有什麼問題能夠在下方留言,感謝。
本篇原始碼 http://download.csdn.net/detail/leejizhou/9459862
Android 組件之Service解析