Android四大元件之服務————服務的生命週期和啟動方式

羸弱的澳龍發表於2020-08-04
ServiceAndroid四大元件之一,是一個計算型元件。它在Android開發中扮演著一個重要的角色,雖然他不如Activity那麼常見,但是在很多App中都有著實際的應用場景。
Service的執行不依賴於任何使用者介面,所以它非常適合用於去執行那些不需要和使用者互動但卻需要長期執行的任務,如App的更新,音樂播放器等。
 
服務有兩種方式:
    開啟服務,停止服務;
    繫結服務,解綁服務;
如下是Service的生命週期:

 

 

下面來體會下服務的方式吧;

 

 給主活動佈局設定五個按鈕,其中第三個是呼叫服務中的方法用的。(不能用new物件的方法呼叫service裡的方法)

 

 

然後再建立一個繼承Service的FirstService類:

其實根據生命週期來,生命週期的方法大致都用到了FirstService上,而我們解綁並未使用unbind方法

 

 

 

 然後用主活動呼叫服務:

 

然後記得在AndroidManifest.xml裡註冊服務,四大元件都是需要在這裡註冊的;

 

 

 

 

 

 這樣就可以測試開啟活動和繫結活動的區別了。。。

 

我們點選開啟服務時,然後呼叫服務內部方法是不行的

 

 

 

 可以看出,繫結服務是可以呼叫服務內部的方法的

 

不過這是總體,細節後面介紹。

兩個啟動服務方式的不同:

  第一個不同:
          通過startSerive()直接啟動服務:
          服務一旦開啟,就與呼叫者沒有任何關係,呼叫者的activity即使退出,也不會影響後臺服務的執行。
 
          通過bindService()繫結服務:
          通過繫結方式開啟的服務,服務跟呼叫者不求同生但求同死。如果呼叫者的activity退出了,那她繫結的服務也會跟著退出。
          注意:如果一個程式的activity繫結了服務,那麼這個activity退出時,會報異常,說是服務沒有被釋放。
          那麼我們可以重寫activity的onDestory方法,方法內呼叫unbindService(),去顯示的解除與服務的繫結。

  第二個不同點:
           Start直接啟動服務的方法,呼叫者不能呼叫服務內部的方法。

           繫結服務啟動服務的方法,呼叫者可以呼叫服務內部的方法;
           利用serviceConnection介面獲取服務onbind返回的ibinder物件,
           這個物件同時實現了自定義的介面,這個介面內定義了服務中的方法。
 
 
那詳細講解如何建立啟動服務吧:
主活動:
package com.example.myservice;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private static final String TAG = MainActivity.class.getName();
private Button button;
private Button button2;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}

private void initView() {
button = (Button) findViewById(R.id.button);
button2 = (Button) findViewById(R.id.button2);
button.setOnClickListener(this);
button2.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
Intent intent = new Intent(this, FirstService.class);
startService(intent);//開啟
break;
case R.id.button2:
Intent intent2 = new Intent(this, FirstService.class);
stopService(intent2);//停止
break;

}
}
}

主活動佈局就是啟動和暫停服務的兩個按鈕

然後繼承服務的類FirstService:
package com.example.myservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.Nullable;

import java.util.logging.Logger;

public class FirstService extends Service {
private static final String TAG = FirstService.class.getName();


@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate...");
}

// 被棄用了,
@Override
public void onStart(Intent intent, int startId) {
Log.d(TAG, "onStart...");
super.onStart(intent, startId);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand...");
return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
}

這種就是簡單的開啟服務的方法;
得記得AndroidManifest註冊FirstService的服務
開啟後根據生命週期的提示給它走完輸出。



繫結服務的方法如下:
主活動:
package com.example.myservice;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private static final String TAG = MainActivity.class.getName();
private Button button3;
private Button button4;
private Button button5;
private FirstService.InnerBinder removeBinf;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}

private void initView() {
button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(this);
button4 = (Button) findViewById(R.id.button4);
button4.setOnClickListener(this);
button5 = (Button) findViewById(R.id.button5);
button5.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button3:
Log.d(TAG, "呼叫服務內部方法。。。");
removeBinf.callInnerMethod();
break;
case R.id.button4:
Log.d(TAG, "繫結服務。。。");
Intent intent4 = new Intent(this, FirstService.class);
bindService(intent4, serviceConnection, BIND_AUTO_CREATE);//繫結
break;
case R.id.button5:
Log.d(TAG, "解綁服務。。。");
if (serviceConnection != null) {
unbindService(serviceConnection);//解綁
}
break;
}
}

private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "連線服務。。。");
removeBinf = (FirstService.InnerBinder) service;

}

@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "未連線服務。。。");
removeBinf = null;
}
};
}
繫結需要三個固定引數,其中第二個是要new的服務連線類的物件和方法。
第三個預設是自動建立,如果建立了就不建立BIND_AUTO_CREATE

然後FirstService類的方法就要使用Onbind()方法了
package com.example.myservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.Nullable;

import java.util.logging.Logger;

public class FirstService extends Service {
private static final String TAG = FirstService.class.getName();

public class InnerBinder extends Binder {
public void callInnerMethod() {
fun();
}
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "繫結中...");

return new InnerBinder();
}

private void fun() {
Toast.makeText(this, "我是一個服務內部方法嘞", Toast.LENGTH_SHORT).show();
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate...");
}

// 被棄用了,
@Override
public void onStart(Intent intent, int startId) {
Log.d(TAG,"onStart...");
super.onStart(intent, startId);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand...");
return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}

}
先寫內部類
public class InnerBinder extends Binder {
public void callInnerMethod() {
fun();
}
}
然後給onbind new一個內部類,在活動裡的ServiceConnection裡使用成員變數
    private FirstService.InnerBinder removeBinf;
  removeBinf = (FirstService.InnerBinder) service;
強轉成服務裡的內部類方法實現繫結效果,然後繫結後用這個成員變數去呼叫服務裡的方法,才可以實現活動呼叫服務內部方法。

這種就是繫結服務的方法;
得記得AndroidManifest註冊FirstService的服務

 

 

最後就成功呼叫了,服務的概念還是比較新奇,需要一段時間去理解接受。

先了解一些概念性的東西可以更好的看懂和理解服務。

 

 



相關文章