編輯:關於Android編程
Service是安卓四大組件之一,服務是用在後台處理事情的,並且是不可見的,該服務不是我們所說的服務器的服務,他經常用來處理一些循環操作,但是它不同於子線程,服務是運行在主線程中的。
服務一般分為本地服務和遠程服務,這裡先介紹本地服務。
本地服務通常用兩種啟動方式
1. 直接啟動模式
我們可以通過startService(Intent intent)方式去直接啟動一個服務,對於intent意圖,我們也可以用兩種形式
創建,一種是顯示啟動,一種是隱示啟動,但是需要注意的是,在android5.0以後,所有的服務盡量通過顯示
意圖來啟動。否則就直接程序崩潰。所以建議都使用顯示方式啟動服務。如果一定要使用隱示啟動方式, 則在對應的intent中添加一句intent.setPackage(對應服務所在的包名),通過這個方法,可以防止5.0後隱示啟動發生崩潰的作用。下面通過代碼來詳細講解下。
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick(View view){
intent = new Intent(this,MyService.class);
//intent.setPackage("cn.itrealman.servicedemo");5.0以後需要加上這句代碼
switch (view.getId()) {
case R.id.start:
//啟動服務
startService(intent);
break;
case R.id.stop:
//停止服務
stopService(intent);
break; }
}
}
在AndroidManifest.xml中配置Service
MyService.java
public class MyService extends Service {
public MyService() {
Log.d("IT_Real", "MyService: 構造方法");
}
/**
* 這個方法是通過綁定的方式才會調用該方法
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
Log.d("IT_Real", "onBind: ");
return null;
}
/**
* 服務啟動後初始化內部數據的方法,只會在第一次啟動該服務的時候調用一次
*/
@Override
public void onCreate() {
Log.d("IT_Real", "onCreate: ");
super.onCreate();
}
/**
* 銷毀服務
*/
@Override
public void onDestroy() {
Log.d("IT_Real", "onDestroy: ");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log.d("IT_Real", "onUnbind: ");
return super.onUnbind(intent);
}
/**
* 這個方法是直接啟動服務時調用的方法,不過該方法已經過時了
* 被下面的onStartCommand方法代替了
* @param intent
* @param startId
*/
@Override
public void onStart(Intent intent, int startId) {
Log.d("IT_Real", "onStart: ");
super.onStart(intent, startId);
}
/**
* 這個方法也是直接啟動服務時調用的方法
* @param intent
* @param flags
* @param startId
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("IT_Real", "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
}
在上面的代碼中,當我們點擊啟動按鈕時,相應的服務被啟動,在此之前,我們先看一下直接啟動方式服務的生命周期圖:
在上面的圖中,我可以了解到,當我們第一次啟動服務時,會先調用onCreate()——>onStartCommand()——onStart(),然後服務會開始運行,直到調用stopService()方法才會停止服務,然後會調用相應的onDestory()方法,如果服務已經啟動,我們多次點擊啟動服務按鈕,則會多次掉用onStartCommand()——>onStart()方法
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxjb2RlPrbU09rJz8PmtcTV4tbWt73KvaOsztLDx7K7u+G78cihyM66zrf+zvG21M/zo6zSsrK7xNyy2df3yM66zrf+zvHA78PmtcTK/b7do6y2vMrHz7XNs9fUvLrIpbLZ1/e1xKOsvNPI68u1o6zO0sPHtcS3/s7xwO/D5tPQ0ru49mRvU3RoKCm3vbeoo6zO0s/ryKW199PD1eK49re9t6jX9rjDysLH6aOsxMfDtLjD1PXDtLX308PE2KO/1eK49sqxuvKjrM7Sw8e+zda7xNzIpc2ouf3U2m9uU3RhcnRDb21tYW5kKCm3vbeowO/D5siltffTw8HLo6jU2m9uU3RhcnSjqKOpt723qNbQ0rK/ydLUtffTw6OstavKx7K7zca89tXi0fnKudPDo6y5/cqxtcS3vbeoztLE3LK708O+zbK708OjqaOstPrC68jnz8I6PC9jb2RlPjwvcD4NCjxwcmUgY2xhc3M9"brush:java;">
/**
* 這個方法也是直接啟動服務時調用的方法
* @param intent
* @param flags
* @param startId
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("IT_Real", "onStartCommand: ");
//通過調用該方法
doSth();
return super.onStartCommand(intent, flags, startId);
}
private void doSth(){
Log.d("IT_Real", "doSth: 我正在做某事...");
}
這樣我們就能完成需要操作的事情了,但是這樣的操作往往會很不方便,不能很好的讓用戶去通過某種方式去操作,比如在播放音樂的時候,我們就會很難去控制服務去處理某些事情,所以一般我們會通過綁定的方式來啟動服務。
2. 綁定啟動模式
對於綁定啟動服務,我們可以很好的獲取到服務給我們返回的Ibinder對象,由於Ibinder是一個接口,通常我們會返回一個Ibinder的子類Binder對象。一般情況下,我們會去繼承Binder對象,添加自己所需要的實現功能。綁定啟動的方式是通過bindService(Intent intent, ServiceConnection conn, int flags)綁定服務,該方法的三個參數如下:
intent:通過Intent指定要啟動的服務
conn:該參數是一個ServiceConnection對象,該對象用於監聽訪問者與service之間的連接情況。當訪問者與Service直接連接成功時將回調ServiceConnection對象的onServiceConnected(ComponentName name, IBinder service)方法,當Service所在的宿主進程由於異常中斷或者其他原因終止,導致該Service與訪問者之間斷開連接時,會調用ServiceConnection對象的onServiceDisconnected(ComponentName name)方法。
flags:指定綁定時,是否通過自動創建Service(未創建的情況下),如果該參數指定0(不創建),或者寫BIND_AUTO_CREATE(自動創建)
創建代碼如下:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Intent intent;
private MyServiceConnection conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
conn = new MyServiceConnection();
}
public void onClick(View view){
intent = new Intent(this,MyService.class);
switch (view.getId()) {
case R.id.bindStart:
bindService(intent,conn,BIND_AUTO_CREATE);
break;
case R.id.bindStop:
unbindService(conn);
break; }
}
/**
* ServiceConnection類,通過該類中的onServiceConnected方法
* 中的IBinder service對象可以獲取到綁定的服務對象中的MyBinder對象
* 然後可以通過MyBinder對象中的getBindService方法獲取我們的
* MyBindService對象
*/
class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//獲取Binder對象
MyBindService.MyBinder service1 = (MyBindService.MyBinder) service;
MyBindService service2 = service1.getBindService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
在AndroidManifest.xml中配置Service
MyBindService.java
public class MyBindService extends Service {
public MyBindService() {
}
/**
* 返回的IBinder對象
*/
class MyBinder extends Binder{
public MyBindService getBindService(){
returnMyBindService.this;
}
}
@Override
public void onCreate() {
Log.d("IT_Real", "onCreate: ");
super.onCreate();
}
/**
* 綁定服務時調用該方法
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
Log.d("IT_Real", "onBind: ");
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent) {
Log.d("IT_Real", "onUnbind: ");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.d("IT_Real", "onDestroy: ");
super.onDestroy();
}
}
這樣我們就可以獲取綁定服務對象了。然後我們看一下下面的生命周期圖
通過綁定服務我們可以看出該生命周期。當調用了bindService方法時,生命周期為onCreate()——>onBind()——>服務運行,當調用unbindService()方法時,服務被關閉,執行onUnbind()——>onDestroy()
通過綁定服務,我們可以獲取到對應的服務對象,如果說要實現某些操作,在服務裡面定義對應的該操作,然後通過服務對象可以去調用該方法。我們去調用一個播放、暫停、上一首、下一首等。代碼如下
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Intent intent;
private MyServiceConnection conn;
private MyBindService service2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
conn = new MyServiceConnection();
}
public void onClick(View view){
intent = new Intent(this,MyBindService.class);
switch (view.getId()) {
case R.id.bindStart:
bindService(intent,conn,BIND_AUTO_CREATE);
break;
case R.id.bindStop:
unbindService(conn);
break;
case R.id.startMusic:
//播放
service2.start();
break;
case R.id.pause:
//暫停
service2.pause();
break;
case R.id.previous:
//上一首
service2.previous();
break;
case R.id.next:
//下一首
service2.next();
break;
}
}
/**
* ServiceConnection類,通過該類中的onServiceConnected方法
* 中的IBinder service對象可以獲取到綁定的服務對象中的MyBinder對象
* 然後可以通過MyBinder對象中的getBindService方法獲取我們的
* MyBindService對象
*/
class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//獲取Binder對象
MyBindService.MyBinder service1 = (MyBindService.MyBinder) service;
service2 = service1.getBindService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
MyBindService.java
public class MyBindService extends Service {
public MyBindService() {
}
/**
* 返回的IBinder對象
*/
class MyBinder extends Binder{
public MyBindService getBindService(){
return MyBindService.this;
}
}
/**
* 服務被創建時調用該方法
*/
@Override
public void onCreate() {
Log.d("IT_Real", "onCreate: ");
super.onCreate();
}
/**
* 綁定服務時調用該方法
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
Log.d("IT_Real", "onBind: ");
return new MyBinder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("IT_Real", "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
/**
* 當調用了unbindService方法是,調用該方法
* @param intent
* @return
*/
@Override
public boolean onUnbind(Intent intent) {
Log.d("IT_Real", "onUnbind: ");
return super.onUnbind(intent);
}
/**
* 被關閉之前調用該方法
*/
@Override
public void onDestroy() {
Log.d("IT_Real", "onDestroy: ");
super.onDestroy();
}
public void start(){
Log.d("IT_Real", "start: 播放");
}
public void pause(){
Log.d("IT_Real", "pause: 暫停");
}
public void next(){
Log.d("IT_Real", "next: 下一首");
}
public void previous(){
Log.d("IT_Real", "previous: 上一首");
}
}
這樣就可以很好的操作服務裡面的方法了。對於綁定服務,有一個地方需要注意,那就是,我們在啟動服務後,如果退出了當前activity,或者結束該進程的時候,沒有調用unbindService()方法,程序會報一個
Activity cn.itrealman.servicedemo.MainActivity has leaked ServiceConnectioncn.itrealman.service
demo.MainActivity$MyServiceConnection@6c1837b that was originally bound here異常
這個異常表示連接已經綁定,我們沒有解綁,會導致洩露問題。所以,一般我們建議在銷毀Activity時,我們需要在Activity的onDestroy()方法中添加如下代碼:
@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
或者說,我們在關閉Activity之前,自己手動調用解綁方法。這樣就能保證我們的程序不出錯。
hello,上篇我們已經分析6種Drawable的使用方法,本篇咱們就繼續剩下的Drawable~,閒話莫多說,那就直接開始吧。7、TransitionDrawable很
先看效果圖: 寫一個超連接支持的對象: /**作為超連接顯示的對象*/ public class LinkInfo implements Comparable{
0.基礎知識Glide中有一部分單詞,我不知道用什麼中文可以確切的表達出含義,用英文單詞可能在行文中更加合適,還有一些詞在Glide中有特別的含義,我理解的可能也不深入,
手機qq可以截圖嗎?有時候想把與某人的聊天記錄截屏保存,或者想在qq浏覽器上保存重要的信息,該怎麼操作呢?下面就隨小編把這項技能gei起來!手機qq怎麼截圖