android Server及IntentServer

一.Android Service服務:

      Android中的服務是運行在後臺的服務,他是不可見的沒有界面的東西。你可以啓動一個服務Service來播放音樂,或者記錄你地理信息位置的改變,或者啓動一個服務來運行並一直監聽某種動作。Service和其他組件一樣,都是運行在主線程中,因此不能用它來做耗時的請求或者動作。你可以在服務中開一一個線程,在線程中做耗時動作。

服務的生命週期圖:

 

 

1.如何創建和開啓一個服務:

第一步:創建一個類 ExampleService.java 繼承android.app.Service

第二步:覆蓋其中繼承的方法 如下:

 

複製代碼
public class ExampleService extends Service
{

    private static final String TAG = "Example";

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

    @Override
    public void onCreate()
    {
        Log.i(TAG, "ExampleService===>>onCreate");
        super.onCreate();
    }

    @Override
    public void onStart(Intent intent, int startId)
    {
        Log.i(TAG, "ExampleService===>>onStart");

        super.onStart(intent, startId);
    }

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

    @Override
    public void onDestroy()
    {
        Log.i(TAG, "ExampleService===>>onDestroy");
        super.onDestroy();
    }

}
複製代碼

 

第三步:啓動服務:

    Intent intent = new Intent(MainActivity.this, ExampleService.class);
    startService(intent);

第四步:關閉服務:

stopService(intent);//關閉服務

服務運行的生命週期順序:

[onCreate()-->onStartCommand()--->onStart()-->運行服務--->調用stopService()--->onDestory()]

在Activity中通過startService()開啓的服務,開啓之後及時現在我們關閉Activity服務還一直在後臺運行,只有調用stopService()才能關閉服務。

關閉Activity之後 我們在此點擊按鈕 重新開啓服務。

注意:服務在後臺運行我們再次點擊startService()開啓服務。將不會在調用 onCreate()服務。一個服務只會創建一次,銷燬一次,但可以開始多次,因此,onCreate和onDestroy方法只會被調用一次,而onStart(或onStartCommand)方法會被調用多次。

如下圖:

 

 

點擊stopService()方法將關閉服務:

 

 注意:onStart方法是在Android2.0之前的平臺使用的.在2.0及其之後,則需重寫onStartCommand方法,同時,舊的onStart方法則不會再被調用.    

 

 

 

二.bindService()

 

      Bound service 允許其它的組件(比如Activities)綁定到這個Service上,可以發送請求,也可以接受請求,甚至進行進程間的通話。Bound service 僅僅在服務於其它組件時存在,不能獨自無限期的在後臺運行。

 

 

     調用者和服務綁在一起,調用者一旦退出服務也就終止[onCreate()-->onBind()-->onUnbind()-->onDestory()]

1.創建Bound Services

 

     當創建一個能提供綁定功能的服務時,我們必須提供一個IBinder對象,客戶端能使用這個對象與服務進行交互。在Android中有三種方式定義方式:

         1.擴展Binder類

         2.使用Messenger

         3.使用AIDL (Android Interface Definition Language)

   創建 步驟:

      第一步:.創建一個類BinderService.java 繼承 android.app.Service

複製代碼
public class BinderService extends Service
{

    public class MyBinder extends Binder
    {
        public BinderService getBinderService()
        {
            return BinderService.this;
        }
    }
    private MyBinder binder=new MyBinder();
    private static final String TAg = "BinderService";
    @Override
    public IBinder onBind(Intent intent)
    {
        Log.i(TAg, "BinderService===>onBind()");
        return binder;
    }
    public void UpFile()
    {
        Log.i(TAg, "BinderService===>UpFile()");
    }
    @Override
    public void onCreate()
    {
        Log.i(TAg, "BinderService===>onCreate()");
        super.onCreate();
    }
    @Override
    public void onDestroy()
    {
        Log.i(TAg, "BinderService===>onDestroy()");
        super.onDestroy();
    }
    @Override
    public boolean onUnbind(Intent intent)
    {
        Log.i(TAg, "BinderService===>onUnbind()");
        return super.onUnbind(intent);
    }
    

}
複製代碼

 

第二步:在Service類中,創建一個Binder實例 包含客戶端能調用的公共方法 返回當前服務對象

 

  

複製代碼
public class MyBinder extends Binder
    {
        public BinderService getBinderService()
        {
            return BinderService.this;
        }
    }
複製代碼

第三步:在onBind()方法中返回Binder實例

複製代碼
    private MyBinder binder=new MyBinder();
    private static final String TAg = "BinderService";
    @Override
    public IBinder onBind(Intent intent)
    {
        return binder;
    }
複製代碼

第四步:在客戶端,從onServiceConnected()方法中獲得Binder實例。

複製代碼
private void bindService()
    {
        Intent intent=new Intent(MainActivity.this,BinderService.class);
        bindService(intent,conn,Context.BIND_AUTO_CREATE);
    } 
   private void unBind()
   {
       if(isConnected)
       {
           unbindService(conn);
       }
   }
    private ServiceConnection conn=new ServiceConnection()
    {
        @Override
        public void onServiceDisconnected(ComponentName name)
        {
           isConnected=false;
            
        }
        @Override//在onServiceConnected 中獲取Binder的實例
        public void onServiceConnected(ComponentName name, IBinder binder)
        {
            MyBinder myBinder=(MyBinder)binder;
            BinderService service=myBinder.getBinderService();
            service.UpFile();
            isConnected=true;
        }
    };
複製代碼

通過調用 bindService()開啓服務 。

調用unBind()關閉服務,或者我們關閉Activity也會關閉服務

 

三.Android中Service運行在主線程中。

    Android 中的服務是運行在主線程上的,通過下面的例子來說明Android服務運行的線程。如果是運行在主線程的,

那在服務中步要運行太耗時的操作。如果運行態耗時的操作將會是整個Activity處於假死狀態,無在進行別的操作。如何要運行耗時操作

要用到多線程Thread 或者異步操作 InentService.

創建一個 MyServiceThread.java 繼承 Service的服務:

 

複製代碼
public class MyServiceThread extends Service
{

    private static final String TAG = "MyServiceThread";

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

    @Override
    public void onCreate()
    {
        Log.i(TAG, "MyServiceThread===>>onCreatre===>>線程ID:"+Thread.currentThread().getId());
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
    
        try
        {
//這裏進行耗時的操作 Log.i(TAG,
"MyServiceThread===>>onStartCommand===>>線程ID:"+Thread.currentThread().getId()); Log.i(TAG, "文件下載。。。。。"); Thread.sleep(5000); Log.i(TAG, "文件下載完成。"); } catch (InterruptedException e) { e.printStackTrace(); } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG, "MyServiceThread===>>onDestroy===>>線程ID:"+Thread.currentThread().getId()); super.onDestroy(); } }
複製代碼

 

程序爲開啓耗時服務時:

    開啓耗時服務時:

運行截圖:下圖可看出Android 中的Service確實是運行在主線程中。從運行前和運行後,當我們點擊開啓服務,按鈕在服務沒有運行

結束時,背景處於黃色,此時不能進行其他的操作。如果要運行耗時的操作需要應用多線程操作。

 

 

三.Android中Service多線程操作運行耗時操作。

    一下演示Android服務如何在多線程下進行耗時操作。

1.創建ManyThreadService.java 服務

複製代碼
public class ManyThreadService extends Service
{

    private static final String TAG = "ManyThreadService";

    @Override
    public IBinder onBind(Intent intent)
    {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onCreate()
    {    
        Log.i(TAG, "ManyThreadService==>>onCreate==>線程ID:"+Thread.currentThread().getId());
    
    }
    private class MyThread extends Thread
    {

        @Override
        public void run()
        {
            
            try
            {
                Log.i(TAG, "ManyThreadService==>>文件下載線程ID:"+Thread.currentThread().getId());
                Log.i(TAG, "文件下載中。。。。。>>文件現在線程ID:"+Thread.currentThread().getId());
                Thread.sleep(5000);
                Log.i(TAG, "文件現在完成。 >>文件下線線程ID:"+Thread.currentThread().getId());
            } catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        
        Log.i(TAG, "ManyThreadService==>>onStartCommand中開啓線程==>線程ID"+Thread.currentThread().getId());
        new MyThread().start();
        return START_STICKY;
    }
    @Override
    public void onDestroy()
    {
        Log.i(TAG, "ManyThreadService==>>onDestory==>線程ID"+Thread.currentThread().getId());
        super.onDestroy();
    }
    

}
複製代碼

2.創建新線程進行耗時操作:

複製代碼
private class MyThread extends Thread
    {

        @Override
        public void run()
        {
            
            try
            {
                Log.i(TAG, "ManyThreadService==>>文件下載線程ID:"+Thread.currentThread().getId());
                Log.i(TAG, "文件下載中。。。。。>>文件現在線程ID:"+Thread.currentThread().getId());
                Thread.sleep(5000);
                Log.i(TAG, "文件現在完成。 >>文件下線線程ID:"+Thread.currentThread().getId());
            } catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        
    }
複製代碼

3.開啓新線程:

複製代碼
public int onStartCommand(Intent intent, int flags, int startId)
    {
        
        Log.i(TAG, "ManyThreadService==>>onStartCommand中開啓線程==>線程ID"+Thread.currentThread().getId());
        new MyThread().start();
        return START_STICKY;
    }
複製代碼

運行效果:從下圖看出出,多線程並行操作,提高執行的效率。如果要在Android服務中執行耗時的並行操作服務,適應多線程操作時不錯的選擇。

如果只是運行異步請求操作 IntentService是不錯的選擇。

 

 

三.Android中IntentSevice操作。

      IntentService是Service類的子類,用來處理異步請求。客戶端通過startService(Intent)方法傳遞請求給IntentService,

 IntentService通過worker thread處理每個Intent對象,執行完所有工作後自動停止Service。

 寫構造方法 複寫onHandleIntent()方法

IntentService執行如下操作 

   1.創建一個與應用程序主線程分開worker thread用來處理所有通過傳遞過來的Intent請求

   2.創建一個work queue,一次只傳遞一個intent到onHandleIntent()方法中,從而不用擔心多線程帶來的問題

   3.當處理完所有請求後自動停止服務,而不需要我們自己調用stopSelf()方法

   4.默認實現了onBind()方法,返回值爲null

   5. 默認實現了onStartCommand()方法,這個方法將會把我們的intent放到work queue中,然後在onHandleIntent()中執行。

創建 MyIntentService.java 繼承:android.app.IntentService

複製代碼
public class MyIntentService extends IntentService
{

    private static final String TAG = "MyIntentService";
    public MyIntentService()
    {
        super("MyIntentService");
    }
    @Override
    public IBinder onBind(Intent intent)
    {
        return null;
    }
    @Override
    public void onCreate()
    {
         Log.i(TAG, "MyIntentService==>>onCreate==>>線程ID:"+Thread.currentThread().getId());
        super.onCreate();
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
         Log.i(TAG, "MyIntentService==>>onStartCommand==>>線程ID:"+Thread.currentThread().getId());
        return super.onStartCommand(intent, flags, startId);
    }
    @Override
    protected void onHandleIntent(Intent intent)
    {
        
        try
        {
            Log.i(TAG, "MyIntentService==>>onHandleIntent==>>線程ID:"+Thread.currentThread().getId());
            Log.i(TAG, "文件下載中。。。。。>>文件下載線程ID:"+Thread.currentThread().getId());
            Thread.sleep(5000);
            Log.i(TAG, "文件現在完成>>文件下載線程ID:"+Thread.currentThread().getId());
        } catch (InterruptedException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        

    }
    @Override
    public void onDestroy()
    {
         Log.i(TAG, "MyIntentService==>>onDestory==>>線程ID:"+Thread.currentThread().getId());
        super.onDestroy();
    }

}
複製代碼

運行效果:從下圖可以看出,在每次開啓服務時傳過去的inent,耗時操作都是有一個線程來執行處理。而所有操作排列成一個線程隊列,先執行完個操作,緊接着

執行下一個操作。執行完所以操作後 服務會自動onDestory操作進行銷燬。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章