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。

Android:Handle与Service

 第一个选项Service(IntentService)表示创建一个继承自IntentService的Servie,后续介绍。

点击Service后,如下界面。

Android:Handle与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方法销毁。

Android:Handle与Service

上一篇:XOR Gate with Truth Table in Proteus ISIS


下一篇:LeetCode 448. Find All Numbers Disappeared in an Array