《第一行代碼》第十章 后臺默默的勞動者 探究Service

  • 本篇參考資料《第一行代碼 第三版》 2020.4月出版
  • 本篇文章只是本人看書的理解和整理的筆記灰瞻,更完整的內(nèi)容還在書上
  • 尊重原作者 請購買正版圖書

一開始就知道有四大組件龙优,結(jié)果學(xué)習(xí)Android開發(fā)這么久愕贡,一直還只用到了Activity济舆,這里需要進行惡補抵怎,從Service開始

四大組件之一 Service

Service是Android中實現(xiàn)程序后臺運行的解決方案浓恶,它非常適合執(zhí)行那些不需要和用戶交互而且還要求長期運行的任務(wù)玫坛。Service的運行不依賴于任何用戶界面,即使程序被切換到后臺包晰,或者用戶打開了另外一個應(yīng)用程序湿镀,Service仍然能夠保持正常運行炕吸。

另外,不要被Service的后臺概念所迷惑勉痴,實際上Service并不會自動開啟線程赫模,所有的代碼都是默認(rèn)運行在主線程當(dāng)中的。也就是說蒸矛,我們需要在Service的內(nèi)部手動創(chuàng)建子線程瀑罗,并在這里執(zhí)行具體的任務(wù),否則就有可能出現(xiàn)主線程被阻塞的情況雏掠。

一. Android多線程編程

當(dāng)我們需要執(zhí)行一些耗時操作斩祭,比如文件的讀寫,網(wǎng)絡(luò)請求等等乡话,為了避免主線程被阻塞影響用戶使用摧玫,一般會放到子線程中執(zhí)行,
這里推薦學(xué)習(xí)框架Rxjava http://www.reibang.com/p/b002d8ea2648
郭神在書上為了方便理解只講了最簡單的多線程實現(xiàn)方式绑青,以下為書中內(nèi)容筆記

1.1 線程的基本用法

比如我們想打印1~10 每次打印間隔1秒
方式一:使用繼承Thread方式:

fun main(){
    val myThread=MyThread()
    myThread.start()
}
class MyThread:Thread(){
    override fun run() {
        super.run()
        for(i in 0..10){
            println(i)
            sleep(1000)
        }
    }
}

方式二:使用實現(xiàn)接口Runnable方式:

fun main() {
    val myThread= MyThread()
    Thread(myThread).start()
}

class MyThread : Runnable {
    override fun run() {
        for (i in 0..10) {
            println(i)
            sleep(1000)
        }
    }
}

可以看到這里是Thread的構(gòu)造函數(shù)接收了一個Runnable參數(shù)诬像,創(chuàng)建了一個Thread對象,再調(diào)用start方法闸婴,就開始了子線程
方式三:使用Lambda表達式 (不需要再專門定義一個類)

fun main() {
    Thread{
        for (i in 0..10) {
            println(i)
            sleep(1000)
        }
    }.start()
}

以上三種再java中也是同樣的用法坏挠,但是接下來,Kotlin為我們提供了一種更簡單的開啟子線程的方式
方式四:使用thread函數(shù)

fun main() {
    thread{
        for (i in 0..10) {
            println(i)
            sleep(1000)
        }
    }
}

可以看到連start也不需要調(diào)用了邪乍,thread函數(shù)內(nèi)部全部幫我們處理好了

1.2 嘗試子線程中更新UI

Android的UI是線程不安全的癞揉,也就是說,如果想要更新應(yīng)用程序里的UI元素溺欧,必須在主線程中進行喊熟,否則就會出現(xiàn)異常。對于這種情況姐刁,Android提供了一套異步消息處理機制芥牌,完美地解決了在子線程中進行UI操作的問題。

接下來我們試試在子線程中更新UI聂使,點擊按鈕壁拉,啟動一個子線程,在子線程中設(shè)置TextView的內(nèi)容:
布局:

    <Button
        android:id="@+id/changeTextBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Change Text"
        />
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25sp"
        android:text="Hello World!"
   />

Activity內(nèi)

import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        changeTextBtn.setOnClickListener {
            thread {
                textView.text = "Nice to meet you !"
            }
        }
    }
}

注意0匕小F怼:這里沒有使用findViewById(),這是Kotlin一個非常優(yōu)秀的設(shè)計,可以直接
import kotlinx.android.synthetic.main.activity_main.*
導(dǎo)入這個界面對應(yīng)的布局layout文件屎蜓,View的id就可以作為對象直接操作

當(dāng)然你非要用findViewById()也可也

private lateinit var button:Button
...
button = findViewById(R.id.button)

使用 Kotlin Android Extensions 直接生成對應(yīng)的 View 作為屬性痘昌。不需要 findViewById,不需要定義變量,直接使用辆苔。使用時需要注意訪問的 View 屬于哪個 Layout算灸,因為智能提示的候選項會提供所有布局中的 View 供你選擇,然后幫你 import 對應(yīng)包以便你訪問這個 View驻啤;假如 import 的多個同一層級的 layout 中具有相同的 id菲驴,則這個 id 對應(yīng)的 View 將無法訪問。

接下來我們運行這個app骑冗,并點擊按鈕赊瞬,可以看到程序崩潰了,出現(xiàn)了一條報錯信息:
Only the original thread that created a view hierarchy can touch its views.
這就證明Android不可以在子線程中操作UI贼涩,那么對于這種情況我們森逮,Android提供了一套異步消息處理機制,完美的解決了在子線程中修改UI的問題

1.3 Android 異步消息處理機制

使用handler接收異步處理的信息磁携,可以在handler中修改ui,將上邊的代碼改成如下:

class MainActivity : AppCompatActivity() {
   //msg識別碼
   val upDataText=10011
   val handler=object:Handler(){
       //接收信息
       override fun handleMessage(msg: Message) {

           super.handleMessage(msg)
           //判斷信息識別碼 根據(jù)不同的識別碼進行不同動作
           when(msg.what){
               //修改ui
               upDataText-> {
                   //讀取參數(shù)對象 并使用as關(guān)鍵字轉(zhuǎn)強制換為Student1類型
                   //msg.obj可能為null 注意使用良风?進行非空判斷
                   var result:Student1?=msg.obj as? Student1
                   //在ui中顯示
                   //如果是空的 則顯示null
                   textView.text=result?.sex?:"null"
               }
           }
       }
   }

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)
       changeTextBtn.setOnClickListener {
           thread {
               val msg=Message()
               //信息識別碼
               msg.what=upDataText
               //msg傳遞一個參數(shù) 對象
               msg.obj=Student1("girl")
               //發(fā)出信息
               handler.sendMessage(msg)
           }
       }
   }
}

在以上的代碼中谊迄,我們將異步線程處理結(jié)果,封裝成一個message傳遞到handler烟央。message主要屬性第一個是msg.what是msg的識別碼统诺,用戶handler判斷不同信息并采取不同動作。msg.obj可以傳遞一些對象參數(shù)疑俭,msg.arg1可以傳遞一些整型參數(shù)粮呢。在handler中,使用as關(guān)鍵字將msg.obj強制轉(zhuǎn)換為具體的類型钞艇,這樣就可以進行操作了啄寡。(注意使用?非空判斷)

1.4 使用AsyncTask來進行異步操作

http://www.reibang.com/p/9724355bf01b

二. Service的使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市哩照,隨后出現(xiàn)的幾起案子挺物,更是在濱河造成了極大的恐慌,老刑警劉巖飘弧,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件识藤,死亡現(xiàn)場離奇詭異,居然都是意外死亡次伶,警方通過查閱死者的電腦和手機痴昧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來冠王,“玉大人赶撰,你說我怎么就攤上這事。” “怎么了扣囊?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵乎折,是天一觀的道長。 經(jīng)常有香客問我侵歇,道長骂澄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任惕虑,我火速辦了婚禮坟冲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘溃蔫。我一直安慰自己健提,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布伟叛。 她就那樣靜靜地躺著私痹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪统刮。 梳的紋絲不亂的頭發(fā)上紊遵,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機與錄音侥蒙,去河邊找鬼暗膜。 笑死,一個胖子當(dāng)著我的面吹牛鞭衩,可吹牛的內(nèi)容都是我干的学搜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼论衍,長吁一口氣:“原來是場噩夢啊……” “哼瑞佩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起坯台,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤钉凌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后捂人,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體御雕,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡走越,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年割捅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漫贞。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡瑟匆,死狀恐怖闽坡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤疾嗅,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布外厂,位于F島的核電站,受9級特大地震影響代承,放射性物質(zhì)發(fā)生泄漏汁蝶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一论悴、第九天 我趴在偏房一處隱蔽的房頂上張望掖棉。 院中可真熱鬧,春花似錦膀估、人聲如沸幔亥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽帕棉。三九已至,卻和暖如春饼记,著一層夾襖步出監(jiān)牢的瞬間香伴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工握恳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捺僻。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓乡洼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親匕坯。 傳聞我的和親對象是個殘疾皇子束昵,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容