Android:Handle與Service


一、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方法銷毀。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM