Service和Activity通信

在上面我們高高興興的啓動了Service了,但是細心的你可能發現了,貌似我們僅僅只是啓動了而已,Activity跟Service並沒有多少"交流",下面我們就讓Activity跟Service交流一下。

public class MyService extends Service {
​
    public static final String TAG = "MyService";
​
    private MyBinder mBinder = new MyBinder();
​
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate() 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;
    }
​
    class MyBinder extends Binder {
​
        public void startDownload() {
            Log.d("TAG", "startDownload() executed");
            // 執行具體的下載任務
        }
​
    }
​
}

接下來我們在MainActivity中通過Button來綁定Service和解除綁定

public class MainActivity extends Activity implements OnClickListener {
        
    private Button bindService;
​
    private Button unbindService;
​
    private MyService.MyBinder myBinder;
​
    private ServiceConnection connection = new ServiceConnection() {
​
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
​
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myBinder = (MyService.MyBinder) service;
            myBinder.startDownload();
        }
    };
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        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.bind_service:
            Intent bindIntent = new Intent(this, MyService.class);
            bindService(bindIntent, connection, BIND_AUTO_CREATE);
            break;
        case R.id.unbind_service:
            unbindService(connection);
            break;
        default:
            break;
        }
    }
​
}

可以看到,這裏我們首先創建了一個ServiceConnection的匿名類,在裏面重寫了onServiceConnected()方法和onServiceDisconnected()方法,這兩個方法分別會在Activity與Service建立關聯和解除關聯的時候調用。在onServiceConnected()方法中,我們又通過 向下轉型 得到了MyBinder的實例,有了這個實例,Activity和Service之間的關係就變得非常緊密了。現在我們可以在Activity中根據具體的場景來調用MyBinder中的任何public方法,即實現了Activity指揮Service幹什麼Service就去幹什麼的功能。
當然,現在Activity和Service其實還沒關聯起來了呢,這個功能是在Bind Service按鈕的點擊事件裏完成的。可以看到,這裏我們仍然是構建出了一個Intent對象,然後調用bindService()方法將Activity和Service進行綁定。bindService()方法接收三個參數,第一個參數就是剛剛構建出的Intent對象,第二個參數是前面創建出的ServiceConnection的實例,第三個參數是一個標誌位,這裏傳入BIND_AUTO_CREATE表示在Activity和Service建立關聯後自動創建Service,這會使得MyService中的onCreate()方法得到執行,但onStartCommand()方法不會執行(只有當我們通過 startService()方法請求啓動服務時,調用此方法)。
解除Activity和Service之間的關聯,調用
unbindService(connection);
關於銷燬Service說明
在MyService的內部通過stopSelf()方法來銷燬的;
一個Service必須要在既沒有和任何Activity關聯又處理停止狀態的時候纔會被銷燬;
在Service的onDestroy()方法裏去清理掉那些不再使用的資源,防止在Service被銷燬後還會有一些不再使用的對象仍佔用着內存;
IntentService
IntentService是Service的子類,在介紹IntentService之前,先來了解使用Service時需要注意的兩個問題
Service 不會專門啓動一個線程執行耗時操作,所有的操作都是在主線程中進行的,以至於容易出現ANR,所以需要手動開啓一個子線程;
Service 不會自動停止,需要調用stopSelf()方法 或者 是stopService() 方法停止;
使用IntentService不會出現這兩個問題,因爲IntentService在開啓Service時,會自動開啓一個新的線程來執行它,另外,當Service運行結束後,會自動停止。
如何保證服務不會被殺死
第一種方式,返回 START_STICKY 或 START_REDELIVER_INTENT
當Service因內存不足而被系統kill後,一段時間後內存再次空閒時,系統將會嘗試重新創建此Service,一旦創建成功後將回調onStartCommand方法,但其中的Intent將是null,除非有掛起的Intent,如pendingintent,這個狀態下比較適用於不執行命令、但無限期運行並等待作業的媒體播放器或類似的服務。

/**
     * 返回 START_STICKY 或 START_REDELIVER_INTENT
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //return super.onStartCommand(intent, flags, startId);
        return START_STICKY;
}

第二種方式,提高service的優先權

<service  
    android:name="com.demo.UploadService"  
    android:enabled="true" >  
    <intent-filter android:priority="1000" >  
        <action android:name="com.demo.MyService" />  
    </intent-filter>  
</service>	
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章