一、Handler消息傳遞機制
進程和線程:
首先來回顧一下這兩個概念
① 進程:一個Android應用就是一個進程,每個應用在各自的進程中進行。例如手機里的app,每一個就是一個進程。
② 線程:比線程更小的獨立運行的基本單位,一個進程可以包含多個線程,且分為一個主線程和多個子線程(子線程也叫Worker線程)
以下例子表示通過子線程運行更改界面內容
public void onClick(View v) { //創建線程 Thread thread = new Thread(new Runnable() { @Override public void run() { textView.setText("你今天的努力是幸運的伏筆,當下的付出是明日的花開。"); } }); thread.start();//開啟線程 }
但運行是失敗的,說明子線程不允許操作主線程的組件。那我們該怎么做呢?
Android提供了Handler對象,我們可以在點擊更改組件按鈕時通知給Handler對象,然后由Handler更新文本框組件。
首先創建Handler
final Handler handler = new Handler(){ @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); } };
然后發送消息,Handler有很多send方法,依次介紹。
handler.sendMessage(Message msg);//發送一個Message對象
handler.sendEmptyMessage(int what);//發送空消息,what表示消息代碼
handler.sendEmptyMessageDelayed(int what,long delayMillis);//表示隔一定時間發送消息 等等。
這樣設置好消息后,可以在之前的handler實例化過程添加下列更換組件信息的代碼。
if(msg.what==0x123){ textView.setText("你今天的努力是幸運的伏筆,當下的付出是明日的花開。"); }
即可達成預期效果。
總結:
Handler是Android提供的一個消息處理機制。
作用:可在任意線程中發送消息,並且可在主線程中獲取消息做出調整。
二、Handler、Looper和MessageQueue的關系
在Android中Handler不是單獨工作的,一起工作的還有Looper,這是一個循環器,主要負責管理MessageQueue(消息隊列,采用先進先出的方式管理消息),Message則在MessageQueue中,在一個線程中,一個handler對象對應一個looper對象,一個looper對象對應一個MessageQueue對象,MessageQueue中存放多個Message。
我們通過Handler獲取Message,將其發送給Looper管理的MessageQueue,此消息處於消息隊列的隊尾,而Looper則會不斷嘗試從MessageQueue中取出未處理的消息,按照隊列先進先出的原則,取出並傳遞給Handler,直到全部消息被取出。
1、Message是怎么攜帶消息的呢?
通過Message對象的屬性來實現的,屬性如下:
1、arg0和arg1屬性,存放整型數據。
2、obj屬性,存放Object類型的數據。
3、replyTo:指定Message發向何處。
4、what:指定用戶自定義的消息代碼,可以使用十六進制的整型。
2、創建Message對象
首先獲取Message對象,但一般不用方法new Message(),用Message對象提供的Message.obtain()或者使用Handler.obtainMessage()來實現。可以避免分配對象,減少內存開發。
實例:實現輪播效果
package com.example.handler_2; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.ImageView; import android.widget.ViewFlipper; public class MainActivity extends AppCompatActivity { final int FLAG_MSG = 0x001; //定義要發送的消息代碼 private ViewFlipper flipper; //定義ViewFlipper private Message message; //聲明消息對象 //定義圖片數組 private int[] images = new int[]{R.drawable.img1, R.drawable.img2, R.drawable.img3, R.drawable.img4, R.drawable.img5, R.drawable.img6, R.drawable.img7, R.drawable.img8}; private Animation[] animation = new Animation[2]; //定義動畫數組,為ViewFlipper指定切換動畫 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /*通過ViewFlipper組件播放廣告*/ flipper = (ViewFlipper)findViewById(R.id.viewFlipper); for(int i=0;i<images.length;i++){ ImageView imageView = new ImageView(this);//創建對象 imageView.setImageResource(images[i]);//將遍歷的圖片保存在ImageView中 flipper.addView(imageView);//加載圖片 } //初始化動畫數組 animation[0] = AnimationUtils.loadAnimation(this,R.anim.slide_in_right); animation[1] = AnimationUtils.loadAnimation(this,R.anim.slide_out_left); flipper.setInAnimation(animation[0]);//設置進入動畫效果 flipper.setOutAnimation(animation[1]);//設置退出動畫效果 //開啟廣告輪播 message = Message.obtain();//獲取Message message.what = FLAG_MSG;//設置消息代碼 handler.sendMessage(message);//發送消息 } /*創建Handler對象,實現3秒更新一次圖片*/ Handler handler = new Handler(){ @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); if (msg.what == FLAG_MSG) { flipper.showPrevious(); //切換到下一張圖片 } message = handler.obtainMessage(FLAG_MSG);//獲取message handler.sendMessageDelayed(msg,3000);//延遲3秒發送消息 } }; }
二、 Service服務
1、定義
能夠在后台長期運行,並且沒有用戶界面的應用程序組件。
2、基本應用
在后台進行下載,播放音樂或定位服務。
3、分類
分為Started Service和Bound Service。
① Started Service:是指調用startService()啟動的Service。此Service不會自動啟動,只有在相應的Activity調用startService()方法才會啟動。
② Bound Service:是指在Activity中調用bindService()方法啟動的Service,使得Service與Activity綁定在一起,若Activity停止,Service也會停止。
4、Service的基本用法
① 創建與配置Service
Android Studio為我們提供了創建Service的向導,我們通過這個可以很方便的創建和使用Service。
第一個選項Service(IntentService)表示創建一個繼承自IntentService的Servie,后續介紹。
點擊Service后,如下界面。
即可創建Service,需要注意的是,如果手動創建類,不用這種方法,需要在AndroidManifest.xml中注冊Service服務,在<application>中添加如下代碼:
<service android:name=".MyService" android:enabled="true" android:exported="true"></service>
② 啟動和停止Service
通過startService(Intent intent)和stopService(Intent intent)方法實現,需要Intent類型參數,Intent intent = new Intent(MainActivity.this,MyService.class); startService(intent) 即可啟動,stopService(intent)即可停止Service。
③ Service的生命周期
Service 類中定義了一系列和自身生命周期相關的方法,在此不一一介紹,最經常使用的有以下三個方法:
- onCreate():當 Service 第一次被創建時,系統調用該方法。
- onStartCommand(Intent intent,int flags,int startId):當通過 startService() 方法啟動 Service 時,該方法被調用。
- onDestroy():當 Service 不再使用時,系統調用該方法。
④ Bound Service
上面介紹的是startService,而當我們需要實現Service與Activity交換數據時,則選擇使用Bound Service。
生命周期:調用bindService()后,調用onCreate()方法,然后調用onBind()方法綁定Service,可以通過unbindService()的onUnBind()方法解除綁定,然后onDestroy方法銷毀。