什麼是服務?java
服務(service)是Android中實現程序後臺運行的解決方案,它很是適合去執行那些不須要和用戶交互並且還要求長期運行的任務。服務的運行不依賴任何的用戶界面,即便應用被切換到後臺或者用戶從新啓動了另外一個程序,服務仍是可以保持正常運行的。安全
不過須要注意的是,服務並非運行在一個獨立的進程裏面,而是依賴於建立服務時所在的程序的進程,當某個程序的進程被殺掉的時候,全部依賴於這個進程的服務就都會被停掉!多線程
固然也不能被服務的後臺概念所迷惑,實際上全部的服務並不會自動開啓線程,全部的代碼都是默認運行在主線程當中的,也就是說咱們須要在服務的內部手動的牀架子線程,並在這裏執行具體的任務,不然就有可能出現主線程被阻塞的狀況。異步
Android多線程得先知道ide
在探究服務這點上咱們首先要明白的是安卓的多線程,咱們這裏學習的也只是安卓多線程最基本以及簡單的東西,雖然本身的水平也只是學習入門的水平,可是按照我對多線程這該耐心的理解,要仔細研究的話多線程裏面的東西是不會少的,好比說線程之間的通訊,由線程安全牽扯出的線程的各類鎖等等,看最簡單的,Android線程的基本用法:工具
// 線程的第一種寫法,直接繼承自Thread自定義咱們的MyThread類 class MyThread extends Thread{ @Override public void run() { super.run(); // 具體的邏輯處理 } } /* * * 那咱們改如何使用這個多線程呢? * 其實也很簡單,咱們直接new 一個 MyThread類 * 而後調用它的start()方法,這樣run方法裏面的具體的操做就在子線程中執行了 * */
咱們還有更好的方式來寫多線程,這種繼承的方式耦合度有點低,更多的時候咱們是選擇實現Runnable()接口的方式來定義一個線程,要是咱們使用了這個方法來實現多線程以後咱們調用的方式也就要發生改變oop
大概的思路仍是: 咱們初始化一個MyThread類,這個類實現一下 Runnable() 接口學習
咱們再初始化一個Thread對象,可是在初始化的時候須要咱們把New出來的MyThread類對象傳入,在以後直接調用start()方法線程
那有沒有更簡單的方式來寫呢?固然是有,也會說咱們最多見的,要是你不想再去定義一個類,咱們就使用下面匿名類的方式來寫,代碼以下:對象
// 使用匿名類的方式使用多線程 new Thread(new Runnable() { @Override public void run() { Log.d("ServiceMainActivity","我是在其餘線程執行的任務") } }).start();
不安全的線程
Android的線程和咱們iOS的線程是同樣的也是不安全的,因此想要在子線程中更新UI是辦不到的,這一點和咱們iOS的同樣,這時候就涉及到主線程和子線程之間的通訊,該如何處理呢?
下面是咱們在異步線程裏面作的操做,在完成咱們發送消息,在主線程接收到消息只有處理任務:
// 線程的第一種寫法,直接繼承自Thread自定義咱們的MyThread類 class MyThread extends Thread{ @Override public void run() { super.run(); // 具體的邏輯處理 Message message = new Message(); message.what = UPDATE_TEXT; handler.sendMessage(message); } }
下面是咱們在主線程作的操縱:
public static final int UPDATE_TEXT = 1; private Handler handler = new Handler(){ // 線程的第一種寫法,直接繼承自Thread自定義咱們的MyThread類 class MyThread extends Thread{ @Override public void run() { super.run(); // 具體的邏輯處理 Message message = new Message(); message.what = UPDATE_TEXT; handler.sendMessage(message); } } };
這樣咱們在異步和主線程之間創建起了通信,其實在主線程和異步線程之間創建通信的方式還有其餘的方式,咱們在接着看異步消息處理機制。
異步消息處理機制
在Android中的異步消息處理主要有四個部分組成: Message Handler MessageQueue Looper
在上一節中,前面的Message和Handler在上一節中咱們已經接觸過了,而MessageQueue和Looper咱們暫時尚未接觸到,下面咱們就對着四部分一點點的剖析一下。
一、Message
Message是在線程之間傳遞的消息,他能夠在內部攜帶少許的信息,用於在不一樣的線程之間交換數據,前面的時候咱們用到的只是簡單的what字段,除此以外可使用arg1和arg2字段類攜帶一些整形數據,使用obj字段能夠攜帶一個object對象。
二、Handler
Handler 顧明思議也就是處理者的意思,它也主要是用於發送和處理消息的,發送消息通常都是使用Handler的sendMessage()方法,而發出的消息通過一系列的展轉處理後,最終會傳遞到Handler的handleMessage()方法。
三、MessageQueue
MessageQueue 是消息隊列的意思,它主要用於存放全部經過Handler發送的消息,這部分消息會一直存放在消息隊列裏面,等待被處理,每一個線程中只會有一個MessageQueue對象。
四、Looper
Looper是每一個線程中的MessageQueue的管家,調用Looper的loop()方法,就會進入到一個無限循環當中,而後每當發現MessageQueue中存放在一條消息,就會將它取出,並傳遞到Handler的handlerMessage()方法中,每個線程中也只會有一個Looper對象。
咱們瞭解了他們的基本概念以後咱們也就能夠看看下面的這張圖了,Android異步消息處理流程圖,經過這張流程圖咱們樂意更好的理解一下這個Android異步消息的處理流程,理解他們四個之間的關係,更好的裂解一下他們的概念:
AsyncTask
爲了更加方便的咱們在子線程中對UI進行操做,Android還提供了擰一個好用的工具,好比AsyncTask,藉助它既是你對異步消息的處理機制徹底不瞭解,也能夠十分簡單的從子線程切換到主線程,固然他背後的實現原理仍是使用了異步消息的處理機制的,只是Android幫咱們分裝好了而已。
AsyncTask首先是一個抽象類,因此咱們想要使用它就必須建立一個子類去繼承它,在繼承的時候咱們能夠爲AsyncTask類指定三個泛型參數:
* params 可用於在後臺任務中使用
* Progress 後臺執行任務的時候,界面要是要顯示進度,可使用這裏指定的泛型做爲進度單位
* Result 若是須要對結果進行參會,則使用這裏指定的泛型做爲返回值類型
除了上面的這三個參數,還有四個方法使咱們在繼承以後須要重寫的:
一、onPreExecute() 後臺任務開始執行以前調用,用於進行一些界面上的初始化操做
二、doInBackground() 耗時操做
三、onProgressUpdate() UI的操做
四、onPostExecute() 任務執行完畢並經過return語句進行返回時,這個方法很快被調用,返回的參數會違參數傳遞到此方法中,處理任務的收尾工做
固然想要啓動個DownLoadTask任務,也只須要咱們執行 new DownLoadTask().execute()方法便可。