Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android編程入門 >> Android 四大組件之Service

Android 四大組件之Service

編輯:Android編程入門

---恢復內容開始---

1,Service的生命周期

onCreate第一次創建service的時候調用。

onStartCommand啟動service的時候調用。

onStart(This method was deprecated in API level 5. Implement onStartCommand(Intent, int, int) instead.

onDestroy銷毀的時候調用。

2,進程優先級(由高到低):(紅色字體的兩個進程是經常被系統回收的兩個進程)
    1. Foreground process 前台進程 用戶正在操作的應用程序的進程.

    2. Visible process    可視進程  用戶可以看到, 但無法進行操作的應用程序的進程.

    3. Service process    服務進程  後台運行的服務所在的進程.(如果有Activity再前台,則該進程屬於前台進程)

    4. Background process 後台進程  最小化應用程序, 托管到後台運行.

    5. Empty process      空進程    已經退出的程序, 沒有任務在運行.

3,service的使用注意事項:

  1.是否可以在service裡寫一些費時操作? 不能。如果有耗時操作可能會導致ANR的發生。 (onReceive方法內是否可以寫耗時操作?原因)
       原因是:service這些回調方法的代碼是運行在主線程上的。

  2.IntentService 該服務已經啟動了一個線程,你不必再啟動了。你要做的事情直接寫到onHandleIntent,它會在子線程裡處理。

三道面試題:

  1. service和activity的區別。
    • activity可以和用戶交互,service可以在後台做些事情而不用跟用戶交互。
    • activity在退出程序後會退出,而對於service,如果沒有顯示的調用停止服務,那麼服務就沒有結束,它仍在後台運行。
    • 最大的區別應該是:沒有服務運行的後台進程叫後台進程,而有服務的後台進程叫服務進程。安卓系統的內存回收經常會回收掉優先級低的後台進程。
  2. 既然程序已經退出,為什麼還保留空進程?
    • 優化用戶體驗。當用戶下次啟動該APP的時候,無需重新給分配進程,節約時間,提高效率。只有當內存不足時采取回收資源。 
  3. service和線程都是在後台運行,那他們之間有什麼關系?
    • service和線程不是一個范疇的東西。service是四大組件之一,是一個特殊的類,在service中可以另起線程。service本身不是運行在一個單獨進程中,默認情況下service是運行在主線程中的。

service的具體使用:

  1. 在activity中啟動service與停止service

  

 //啟動服務
 Intent intent = new Intent(this,MyService.class);
 startService(intent);
 //停止服務
 Intent intent = new Intent(this, MyService.class);
 stopService(intent);

 

  2,activity通過綁定service,可以調用服務內的方法(activity如果關閉的話,service也會結束)

//在Activity中調用本地服務(同一個應用中的服務)中的方法:
//1.調用bindservice去綁定服務,傳遞一個連接橋對象
//2.在service內部去繼承一個Binder,實現的子類 。該子類可以隨意調用service內的方//法。
//3.在onBind方法中,返回該子類的實現。
//4.當綁定ok,連接橋建立成功之後,連接橋對象的onServiceConnected 會被調用到,  這裡面會返回一個IBinder對象,該對象就是onBind返回的那個。
//5.拿到這個IBinder對象之後,強轉為MyBinder接收,然後調用其方法即可。

//綁定和解綁服務
public void bindservice(View view){
        //綁定服務
        Intent intent = new Intent(this, MyService.class);
        myServiceConnection = new MyServiceConnection();
        bindService(intent, myServiceConnection, BIND_AUTO_CREATE);

    }

    public void unbindservice(View view){
        //解綁服務
        if(myServiceConnection!=null){
            unbindService(myServiceConnection);
        }
    }
    public void callLocalServiceMetod(View view){
        //調用本地方法
        if(binder!=null){
            Log.i("MyService","調用本地方法");
            final String callParentMethod = binder.callParentMethod();
            final int count = binder.getcount();
            Toast.makeText(this,callParentMethod+count,Toast.LENGTH_SHORT).show();
        }
    }
    class MyServiceConnection implements ServiceConnection{
        //服務建立起來的時候調用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if(service!=null){
                binder = (MyService.MyBinder) service;
            }
            Log.i("MyServiceConnection","onServiceConnected");
        }
        //服務連接斷開的時候調用
        //onServiceDisconnected() 在連接正常關閉的情況下是不會被調用的, 該方法只在Service 被破壞了或者被殺死的時候調用.
        // 例如, 系統資源不足, 要關閉一些Services,
        // 剛好連接綁定的 Service 是被關閉者之一,  這個時候onServiceDisconnected() 就會被調用。
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("MyServiceConnection","onServiceDisconnected");

        }
    }

//service方法
public class MyService extends Service {
    public int count;
    public boolean flag=true;
    public MyService() {
    }
    public String getName(){
        return "I am MyService";
    }
    class MyBinder extends Binder{
        //binder是用來傳輸數據的
        public String callParentMethod(){
            return getName();
        }
        public int getcount(){
            return count;
        }

    }
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("MyService", "onCreate");
        new Thread(){
            @Override
            public void run() {
                super.run();
                //一綁定上就開始做服務
                while(flag){
                    count++;
                    try {
                        Thread.sleep(1000);

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.i("通過綁定的服務開始了",""+count);
                }
            }
        }.start();
        //調用本地方法是的返回值
        return new MyBinder();
        //
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("MyService","onCreate");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("MyService", "onDestroy");
        flag=false;
    }

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

      3,進程間通信(IPC)(Android使用一種接口定義語言AIDL(Android Interface Definition Language)來公開服務的接口的方式來暴露服務接口)

進程間通信實現過程: 
1. 定義服務類.
2. 定義aidl接口文件.
3. 在服務中onbind方法中返回實現aidl接口stub的對象.
4. 在另一個程序中調用bindService方法綁定服務.
5. 拷貝aidl接口文件(包括包名)到另一個程序中.
6. 在onServiceConnected方法中把Ibinder對象轉換成aidl接口對象.
7. 使用接口對象調用方法(至此調用到遠程服務的方法, 實現進程間通信)

//被調用的遠程service
//接口
package com.rgd.day16_bindservice;

// Declare any non-default types here with import statements

interface MyAIDLInterface {
   String callParentMethod();
   int getcount();
}
//遠程service要寫的
class MyBinder2 extends MyAIDLInterface.Stub{
        @Override
        public String callParentMethod() throws RemoteException {

            return getName();
        }

        @Override
        public int getcount() throws RemoteException {
            return count;
        }
    }
//本地調用要寫的
class MyConnection implements ServiceConnection{
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if(service!=null){
                binder = MyAIDLInterface.Stub.asInterface(service);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

    public void bindremoteservice(View view){
        //綁定遠程服務
        Intent intent = new Intent();
        intent.setAction("com.ren.myservice");
        intent.setPackage("com.rgd.day16_bindservice");
        myConnection = new MyConnection();
        bindService(intent, myConnection,BIND_AUTO_CREATE);

    }

    public void unbindremoteservice(View view){
        //解綁遠程服務
        if(myConnection!=null){
            unbindService(myConnection);
        }
    }

    public void callremoteServiceMetod(View view){
        //調用遠程服務的方法
        if(binder!=null){
            try {
                String s = binder.callParentMethod();
                int getcount = binder.getcount();
                Toast.makeText(this,s+getcount,Toast.LENGTH_SHORT).show();
            } catch (RemoteException e) {
                e.printStackTrace();
            }

        }

    }

 

 

               

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved