Android日記之Service的基本使用

前言

上回小米面試問到Servic的時候懵了一下,因為基本很少用到淤井,現(xiàn)在就再次來復習一下己英。

正文

Service的生命周期

Service的生命周期

Service屬于Android的四大組件之一,運行在主線程當中赞警,適用場景在不需要跟用戶交互而又需要長期運行的任務的時候可以用到Service弄跌。
Service的使用方法主要分為兩種甲喝,startService()bindService(),兩種的生命周期稍微不一樣铛只,這里著重說幾點俺猿。

1.每調(diào)用一次startService()就會調(diào)用一次onStartCommand()生命周期,但是onCreate是只調(diào)用一次的格仲。
2.Service通過BindService()綁定后,將會一直運行下去诵冒,直到使用unBindService()方法或者它的Activit被銷毀才回結(jié)束凯肋。
3.如果方法已經(jīng)被綁定了,在沒有解綁的情況下汽馋,stopService()是無法停止服務的侮东,就算生命周期走到了onDestroy()也無法停止。
4.如果一開始先調(diào)用startService()方法后再去調(diào)用BindService()后豹芯,需要同時StopService()unBIndService()方法才能同時銷毀悄雅。

如何使用Service

public class MyService extends Service {
     
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

首先看代碼,使用一個Service就是要繼承這個類铁蹈,然后必須重寫onBind這個方法宽闲,我們先暫時不看這個方法,那一些處理業(yè)務邏輯的方法要寫在哪呢?這時我們就可以重寫Service中其他的一些方法了容诬。

public class MyService extends Service {

    public MyService() {
    }
    
    //先不看這個方法
    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
    
    
    @Override
    public void onCreate() {
        super.onCreate();
    }

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

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

這里又重寫了三個方法娩梨,onStartCommand()我們已經(jīng)講過了,每次啟動一次Service就會調(diào)用一次這個方法览徒,onCreate()會在服務創(chuàng)建的時候調(diào)用狈定,onDestroy()就會在服務銷毀的時候調(diào)用。
一般來說邏輯業(yè)務都是寫在onStartCommand()方法里的习蓬,需要銷毀資源的時候就是在onDestroy()里面纽什。需要注意的是,每一個Service和Activity一樣躲叼,都需要再AndroidManifest.xml進行注冊才能使用芦缰。

 <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"></service>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

啟動服務

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button b1, b2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        b1 = findViewById(R.id.button1);
        b2 = findViewById(R.id.button2);
        b1.setOnClickListener(this);
        b2.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button1:
                Intent startIntent = new Intent(this,MyService.class);
                startService(startIntent);
                break;
            case R.id.button2:
                Intent stopIntent = new Intent(this,MyService.class);
                stopService(stopIntent);
                break;
            default:
                break;
        }
    }
}

創(chuàng)建兩個button,一個啟動服務一個停止服務押赊,我們通過Intent來進行實現(xiàn)的饺藤。啟動服務的時候服務會一直在運行狀態(tài),知道點擊了停止服務的按鈕服務才會停止下來流礁,那有沒有其他的辦法不通過停止按鈕來進行服務停止呢涕俗。這時候只要在Service的任何要停止的位置調(diào)用stopSelf()就可以停止服務了。

public class MyService extends Service {

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }


    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("ServiceDemo","onCreate:服務創(chuàng)建");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("ServiceDemo","onStartCommand:服務在執(zhí)行");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("ServiceDemo","onDestroy:服務銷毀");
    }
}
依次點擊啟動按鈕和停止按鈕的生命周期如圖

Activity和Service進行通信

我在這里寫一個例子舉例這兩個怎么進行交互神帅,因為通過剛才的學習再姑,發(fā)現(xiàn)Activity只負責啟動和停止Service后好像就沒什么用的,這時候就用到我們剛才忽略的onBind()方法了找御。

public class DownLoadBinder extends Binder {

    public void startDownLoad(){
        Log.d("","startDownLoad excuted");
    }

    public int getDonwload(){
        Log.d("","getDonwload excuted");
        return 0;
    }
    
}

使用這個方法之前我們需要創(chuàng)建一個Binder對象一起配合實現(xiàn)功能元镀,我們這里模擬一個下載功能,創(chuàng)建一個DownLoadBinder來繼承Binder來實現(xiàn)霎桅。

public class MyService extends Service {


    private DownLoadBinder downLoadBinder = new DownLoadBinder();

    public MyService() {
    }

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

然后實例化這個類栖疑,直接在onBind()方法里返回就好了,接下來在MainActivity修改滔驶。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button b1, b2, bind, unBind;
    private DownLoadBinder downLoadBinder = new DownLoadBinder();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //這兩個是啟動和開始服務按鈕
        b1 = findViewById(R.id.button1);
        b2 = findViewById(R.id.button2);
        //這兩個是綁定和解綁服務按鈕
        bind = findViewById(R.id.bind);
        unBind = findViewById(R.id.unBind);
        b1.setOnClickListener(this);
        b2.setOnClickListener(this);
        bind.setOnClickListener(this);
        unBind.setOnClickListener(this);
        
        
        
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button1:
                Intent startIntent = new Intent(this, MyService.class);
                startService(startIntent);
                break;
            case R.id.button2:
                Intent stopIntent = new Intent(this, MyService.class);
                stopService(stopIntent);
                break;
            case R.id.bind:
                //綁定服務
                Intent bindService = new Intent(this,MyService.class);
                bindService(bindService,connection,BIND_AUTO_CREATE);
                break;
            case R.id.unBind:
                unbindService(connection);
                //解綁服務
                break;
            default:
                break;
        }
    }
    
    //創(chuàng)建ServiceConnect
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            downLoadBinder = (DownLoadBinder) service;
            downLoadBinder.startDownLoad();
            downLoadBinder.getDonwload();
        }
        
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
}

這里首先創(chuàng)建一個ServiceConnection的匿名類遇革,重寫兩個onServiceConnected()onServiceDisconnected()這兩個方法,然后通過綁定服務的時候調(diào)用揭糕,這時候我們就可以在Activity場景中調(diào)用DownloadBinder的方法了萝快,在綁定的方法里面需要接受三個參數(shù),第一就是剛剛構(gòu)建的Intent對象著角,第二個就是創(chuàng)建出來的ServiceConnection實例揪漩,第三個是標志位,這里傳入的BIND_AUTO_CREATE表示綁定后就會自動創(chuàng)建服務吏口,這時候服務才會開始執(zhí)行奄容。MyService不僅能和這個Activity進行綁定沙廉,跟其它Activity進行綁定也是可以的北发。

InetntService

剛剛也說過Service是運行在主線程的勺美,所以說如果運行一些很耗時的服務谣拣,就很容易造成ANR(Application not Responding),這個時候就需要多線程的幫助了,而這Intent就是為此而生的叁怪。我們可以把這個類看成是HandlerThread和Service的結(jié)合體审葬。在這個類里開啟一個子線程,然后做一些耗時的操作奕谭。它是一個異步的會自動停止的類涣觉。

public class MyIntentService extends IntentService {
   
    public MyIntentService(String name) {
        super(name);
    }

    @Override
    protected void onHandleIntent(@androidx.annotation.Nullable @Nullable Intent intent) {
        //具體邏輯
    }
}

使用方法和Service差不多,耗時的操作寫在onHandleIntent()里血柳,它首先要提供一個構(gòu)造函數(shù)官册,然后調(diào)用父類的構(gòu)造函數(shù)。IntentService也是可以啟動多次的难捌,每次也只會執(zhí)行一個工作線程膝宁,然后執(zhí)行完在執(zhí)行下一個,依次進行下去根吁。關(guān)于IntentService一些具體的使用注意员淫,后面會寫一章源碼分析來進行講解。

參考

  • [郭霖] 第一行代碼Android(第二版)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末击敌,一起剝皮案震驚了整個濱河市介返,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沃斤,老刑警劉巖圣蝎,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異衡瓶,居然都是意外死亡徘公,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門哮针,熙熙樓的掌柜王于貴愁眉苦臉地迎上來步淹,“玉大人,你說我怎么就攤上這事诚撵。” “怎么了键闺?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵寿烟,是天一觀的道長。 經(jīng)常有香客問我辛燥,道長筛武,這世上最難降的妖魔是什么缝其? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮徘六,結(jié)果婚禮上内边,老公的妹妹穿的比我還像新娘。我一直安慰自己待锈,他們只是感情好漠其,可當我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著竿音,像睡著了一般和屎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上春瞬,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天柴信,我揣著相機與錄音,去河邊找鬼宽气。 笑死随常,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的萄涯。 我是一名探鬼主播绪氛,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼窃判!你這毒婦竟也來了钞楼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤袄琳,失蹤者是張志新(化名)和其女友劉穎询件,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唆樊,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡宛琅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了逗旁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘿辟。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖片效,靈堂內(nèi)的尸體忽然破棺而出红伦,到底是詐尸還是另有隱情,我是刑警寧澤淀衣,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布昙读,位于F島的核電站,受9級特大地震影響膨桥,放射性物質(zhì)發(fā)生泄漏蛮浑。R本人自食惡果不足惜唠叛,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沮稚。 院中可真熱鬧艺沼,春花似錦、人聲如沸蕴掏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽囚似。三九已至剩拢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饶唤,已是汗流浹背徐伐。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留募狂,地道東北人办素。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像祸穷,于是被迫代替她去往敵國和親性穿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,562評論 2 349