Android Service筆記

學習瞭一下Service,網上常見的一些就不說瞭,說一下感覺容易給人造成誤解的地方
 
1. 如Service的創建都是在新進程創建的麼?
 
其實不是的,在 Dev Guide中寫道:
Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.
就是說,當創建一個Service的時候,默認是在Application的進程裡主UI線程創建的,如果你在Service中進行阻塞的操作,會直接阻塞UI線程,可能導致五秒無響應的提醒,所以官方建議是在Service裡面創建新的線程來防止阻塞放生。
 
2. 如何在新進程裡創建Service?
一般的方法就是在manifast中聲明Service的時候,使用process標簽,註明所使用的進程,默認使用當前程序主進程:
<service
    android:name="org.foreal.MusicServiceTest"
    android:enabled="true"
    android:process=":music_process"
></service>
 
其中如果進程的名字時以 ":"開頭的,說明進程是當前程序的私有進程,其他程序無法訪問,如果是以小寫字母開頭的進程,說明進程是一個全局的進程,多個程序都可訪問此進程,達到多程序共享進程的目的。
 
3.如果不用新進程的Service,如何方便的進行一些阻塞操作?
可以繼承IntentService來編寫自己的Service,IntentService會自動創建一個worker thread,來進行操作如:
 
public class MyIntentService extends IntentService {
   
    private final static String TAG = "MyIntentService";

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i(TAG, "onHandleIntent");
       
        try {
            synchronized (this){
                wait(3000);
            }
            Log.i(TAG, "完成一次");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
 
其中隻需要重寫onHandleIntent方法來處理自己的操作就行,其中每一次的操作都會進去隊列中,按順序串行執行。
其中要註意的是,IntentService在執行完隊列中所有操作以後會自動銷毀當前Service,也就是說,如果你onHandleIntent中是個非阻塞操作的話,很可能每次調用結束以後Service都被銷毀,然後下次在建立新的Service。
此類可以很方便的完成大多數工作,但是如果要進行並發操作的Service,此類就不適合,應自己實現。
 
3. 如何使Service私有?

如果在Service中聲明intent filter,那麼其他程序也可以通過你聲明的intent filter來訪問你的Service,為瞭避免這種情況,首先你可以去掉intent filter,每次調用Service都使用Intent(Context, Class)的形式,但是,如果喜歡用intent filter的形式,可以使用exported標簽,來使Service私有,這樣即使定義intent filter,其他程序也無法訪問。
 
4.如果一個Service在startService以後 又進行瞭bindService那麼他的生命周期是怎樣的,stopService能否結束掉Service?
答案是不能的,如果一個Service進行瞭bind操作,那麼再進行stopService是無法結束掉此Service,知道綁定的Context全部結束,或解除綁定,Service才會被結束。
 
5. Service 中Onstart方法中,參數startid是什麼意思,又有什麼用處?
因為在使用startService開啟一個Service以後,必須手動的關閉Service,所以Service可能自己調用 stopSelf 方法,來在任務完成的時候結束掉自己。
但是這個時候就會出現一個問題,如果startService調用瞭2次,那麼就執行瞭兩次onStart操作,在第一次onStart操作結束以後,Service可能會認為任務已經完成,並結束掉自己,這個時候第二次的onStart可能還沒結束,導致瞭任務還未完成就被強行關閉瞭。
而startid代表當前onStart被調用的一個編號,在結束Service時候,調用stopSelf(startid),這樣Service就可以檢查,此startid是否是最近一次調用的,如果是,那麼才結束Service,否則不結束。
 
如有錯誤,歡迎指出探討。
 
 
manifest

 

作者 達小生

發佈留言