zoukankan      html  css  js  c++  java
  • 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方法销毁。

  • 相关阅读:
    用Java实现一个简单的DBMS(总结)
    Android小记(整理一下自己犯过的错误)
    在华为云上开启FTP服务并建立FTP站点来从本地向服务器发送和下载文件
    AS中使用真机调试时出现解析错误的问题
    AS中加载gradle时出现Gradle sync failed: Could not find com.android.tools.build:gradle.的错误
    解决AS加载gradle时出现的Could not find com.android.tools.build:gradle:3.5.0.的错误
    过滤器
    View的呈现
    Asp.net MVC Action同步异步执行
    Model验证
  • 原文地址:https://www.cnblogs.com/dongao/p/12290402.html
Copyright © 2011-2022 走看看