Service詳解

onCreate()方法只會在Service第一次被創(chuàng)建的時候調(diào)用,如果當(dāng)前Service已經(jīng)被創(chuàng)建過了,不管怎樣調(diào)用startService()方法,onCreate()方法都不會再執(zhí)行。

Service和Activity通信

Activity通過binder來啟動或停止service中的任務(wù),并監(jiān)聽service中任務(wù)的進(jìn)度。代碼如下:
OnProgressListener

public interface OnProgressListener {
    void onProgress(int progress);  
}  

MyService

public class MyService extends Service {

    private final String TAG = "MyService";
    private int progress = 0;

    private MyBinder mBinder = new MyBinder();


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

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.d(TAG, "onStart() executed");
    }

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

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

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

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind() executed");
        return super.onUnbind(intent);
    }

    class MyBinder extends Binder {
        /**
         * 更新進(jìn)度的回調(diào)接口
         */
        private OnProgressListener onProgressListener;

        public void startDownload() {
            Log.d(TAG, "startDownload() executed");
            // 執(zhí)行具體的下載任務(wù)
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                progress++;
                //進(jìn)度發(fā)生變化通知調(diào)用方
                if (onProgressListener != null) {
                    onProgressListener.onProgress(progress);
                }
            }
        }

        public void stopDownload() {
            Log.d(TAG, "stopDownload() executed");
            // 執(zhí)行具體的下載任務(wù)
        }

        /**
         * 注冊回調(diào)接口的方法,供外部調(diào)用
         *
         * @param onProgressListener
         */
        public void setOnProgressListener(OnProgressListener onProgressListener) {
            this.onProgressListener = onProgressListener;
        }
    }
}

MainActivity中

public class MainActivity extends AppCompatActivity {
    MyService.MyBinder myBinder = null;
    Button btn_start,btn_stop;
    private String Tag = "MyService";
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myBinder = (MyService.MyBinder) service;
            myBinder.setOnProgressListener(new OnProgressListener() {
                @Override
                public void onProgress(int progress) {
                    Log.i(Tag,"progress: "+progress);
                }
            });
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_start = (Button)findViewById(R.id.btn_start);
        btn_stop = (Button)findViewById(R.id.btn_stop);
        Intent bindIntent = new Intent(this, MyService.class);
        bindService(bindIntent, connection, BIND_AUTO_CREATE);
        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myBinder.startDownload();
            }
        });
        btn_stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myBinder.stopDownload();
            }
        });
    }
}

bindService和startService的區(qū)別

  1. 生命周期的區(qū)別:
    startService,【onCreate()- >onStartCommand()->startService()->onDestroy()】
    補充說明:其中沒有onStart(),主要是被onStartCommand()方法給取代了,onStart方法不推薦使用了;
    bindService(),【onCreate()->onBind()->onUnbind()->onDestroy()】
    補充說明:傳遞給bindService()的Intent對象會傳遞給onBind(),傳遞給unbindService()的Intent對象會傳遞給onUnbind()方法。調(diào)用順序為:onCreate --> onBind(只一次,不可多次綁定) --> onUnbind --> onDestory。
  2. 調(diào)用者和服務(wù)者之間的關(guān)系:
    startService()的調(diào)用,調(diào)用者和服務(wù)之間沒有聯(lián)系,即使調(diào)用者退出了,服務(wù)依然在進(jìn)行。
    bindService()調(diào)用者和綁定者綁在一起,調(diào)用者一旦退出服務(wù)也就終止了。
    注意:BroadcastReceiver只能通過startService啟動Service,因為廣播本身生命周期很短,bind的話沒有意義。
  3. 關(guān)于多次調(diào)用:
    多次調(diào)用startService,該Service只能被創(chuàng)建一次,即該Service的onCreate方法只會被調(diào)用一次。但是每次調(diào)用startService,onStartCommand方法都會被調(diào)用。Service的onStart方法在API 5時被廢棄,替代它的是onStartCommand方法。
    第一次執(zhí)行bindService時,onCreate和onBind方法會被調(diào)用,但是多次執(zhí)行bindService時,onCreate和onBind方法并不會被多次調(diào)用,即并不會多次創(chuàng)建服務(wù)和綁定服務(wù)。
  4. 既使用startService又使用bindService的情況
    如果一個Service又被啟動又被綁定,則該Service會一直在后臺運行。首先不管如何調(diào)用,onCreate始終只會調(diào)用一次。對應(yīng)startService調(diào)用多少次,Service的onStartCommand方法便會調(diào)用多少次。Service的終止,需要unbindService和stopService同時調(diào)用才行。不管startService與bindService的調(diào)用順序,如果先調(diào)用unbindService,此時服務(wù)不會自動終止,再調(diào)用stopService之后,服務(wù)才會終止;如果先調(diào)用stopService,此時服務(wù)也不會終止,而再調(diào)用unbindService或者之前調(diào)用bindService的Context不存在了(如Activity被finish的時候)之后,服務(wù)才會自動停止。
    那么,什么情況下既使用startService,又使用bindService呢?
    如果你只是==想要啟動一個后臺服務(wù)長期進(jìn)行某項任務(wù)同時還想要與正在運行的Service取得聯(lián)系,那么有兩種方法:一種是使用broadcast,另一種是使用bindService。前者的缺點是如果交流較為頻繁,容易造成性能上的問題,而后者則沒有這些問題。因此,這種情況就需要startService和bindService一起使用了。
    另外,如果你的服務(wù)只是公開一個遠(yuǎn)程接口,供連接上的客戶端(Android的Service是C/S架構(gòu))遠(yuǎn)程調(diào)用執(zhí)行方法,這個時候你可以不讓服務(wù)一開始就運行,而只是bindService,這樣在第一次bindService的時候才會創(chuàng)建服務(wù)的實例運行它,這會節(jié)約很多系統(tǒng)資源,特別是如果你的服務(wù)是遠(yuǎn)程服務(wù),那么效果會越明顯(當(dāng)然在Servcie創(chuàng)建的是偶會花去一定時間,這點需要注意)
  5. 銷毀 service
    Bind Service -> Unbind Service
    Start Service -> Stop Service
    Bind Service + Start Service -> Unbind Service + Stop Service(無順序區(qū)別)
    ==注意點==
    onServiceDisconnected 會在程序意外退出時才會調(diào)用

參考

startService與bindService的區(qū)別

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容