Android四大組件之服務(一)

服務是什麼
服務(Service)是Android中實現程序後臺運行的解決方案,它非常適合用於去執行那些不需要和用戶交互而且還要求長期運行的任務。服務的運行不依賴於任何用戶界面,即使當程序被切換到後臺,或者用戶打開了另外一個應用程序,服務仍然能夠保持正常運行。
不過需要注意的是,服務並不是運行在一個獨立的進程當中的,而是依賴於創建服務時所在的應用程序進程。當某個應用程序進程被殺掉時,所有依賴於該進程的服務也會停止運行。

另外,也不要被服務的後臺概念所迷惑,實際上服務並不會自動開啓線程,所有的代碼都是默認運行在主線程當中的。也就是說,我們需要在服務的內部手動創建子線程,並在這裏執行具體的任務,否則就有可能出現主線程被阻塞住的情況。

一個簡單的演示

創建服務類:

public class MyService extends Service {
    @Nullable
    //onBindService中的唯一抽象方法
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

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

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

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


主活動

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button startService;
    private Button stopService;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startService = (Button) findViewById(R.id.start_service);
        stopService = (Button) findViewById(R.id.stop_service);
        startService.setOnClickListener(this);
        stopService.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.start_service:
                Intent startIntent = new Intent(this, MyService.class);
                startService(startIntent); // 啓動服務
                break;
            case R.id.stop_service:
                Intent stopIntent = new Intent(this, MyService.class);
                stopService(stopIntent); // 停止服務
                break;
            default:
                break;
        }
    }
}
以上代碼可以看出佈局爲兩個button,用以控制服務的啓動與停止

Android慣例(不解釋):

onCreate()方法是在服務第一次創建的時候調用的,而onStartCommand()方法則在每次啓動服務的時候都會調用。


活動與服務的聯動(onBind)

首先我們需要創建內部類用於模擬服務中的任務(以下載爲例)
public class MyService extends Service {
    //活動與服務的聯動
    private DownloadBinder mBinder = new DownloadBinder();
    //內部類爲活動提供控制服務中下載功能的接口
    class DownloadBinder extends Binder {
        public void startDownload() {
            Log.d("serviceTest", "startDownload executed");
        }
        public int getProgress() {
            Log.d("serviceTest", "getProgress executed");
            return 0;
        }
    }

    @Nullable
    //onBindService中的唯一抽象方法,bindService方法會回調該方法以獲取IBbinder實例
    @Override
    public IBinder onBind(Intent intent) {
        //返回內部類對象
        return mBinder;
    }

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

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("serviceTest","Service onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }
}
在活動中添加內部類的實例(serviceConnection)作爲bindService的參數
public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button startService;
    private Button stopService;
    private Button bindService;
    private Button unbindService;
    private MyService.DownloadBinder downloadBinder;
    private ServiceConnection serviceConnection = new ServiceConnection() {
        //成功綁定
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //BindlerAndroid中的一種跨進程通信方式,它實現了IBinder接口
            downloadBinder = (MyService.DownloadBinder) service;//向下轉型
            downloadBinder.getProgress();
            downloadBinder.startDownload();
        }
        //解除綁定
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startService = (Button) findViewById(R.id.start_service);
        stopService = (Button) findViewById(R.id.stop_service);
        startService.setOnClickListener(this);
        stopService.setOnClickListener(this);
        bindService = (Button) findViewById(R.id.bind_service);
        unbindService = (Button) findViewById(R.id.unbind_service);
        bindService.setOnClickListener(this);
        unbindService.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.start_service:
                Intent startIntent = new Intent(this, MyService.class);
                startService(startIntent); // 啓動服務
                break;
            case R.id.stop_service:
                Intent stopIntent = new Intent(this, MyService.class);
                stopService(stopIntent); // 停止服務
                break;
            //BIND_AUTO_CREATE 表示在活動和服務進行綁定後自動創建服務
            case R.id.bind_service:
                Intent bindIntent = new Intent(this, MyService.class);
                bindService(bindIntent, serviceConnection, BIND_AUTO_CREATE); // 綁定服務
                break;
            case R.id.unbind_service:
                unbindService(serviceConnection); // 解綁服務
                break;
            default:
                break;
        }
    }
}
佈局如下:


結果演示:



服務的生命週期

  一旦在項目的任何位置調用了 ContextstartService()方法,相應的服務就會啓動,並回調onStartCommand()方法。如果這個服務之前還沒有創建過,onCreate()方法會先於onStartCommand()方法執行。服務啓動了之後會一直保持運行狀態,直到stopService()stopSelf()方法被調用。注意雖然每調用一次startService()方法,onStartCommand()就會執行一次,但實際上每個服務都只會存在一個實例。所以不管你調用了多少次startService()方法,只需調用一次stopService()stopSelf()方法,服務就會停止下來了。

若對一個服務既調用了startService()方法,又調用了bindService()方法,如何才能讓服務銷燬掉呢?

根據Android 系統的機制,一個服務只要被啓動或者被綁定了之後,就會一直處於運行狀態,必須要讓以上兩種條件同時不滿足,服務才能被銷燬。所以,這種情況下要同時調用 stopService()unbindService()方法,onDestroy()方法纔會執行。

最簡單的使用了,以後水平夠了補上源碼角度的解析,,,額,還有個IntentService呢,回頭和多線程編程一起補上。

發佈了195 篇原創文章 · 獲贊 194 · 訪問量 67萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章