第三章 服务和广播

本文深入讲解了Android开发中的核心机制,包括线程与Handler异步消息处理机制、服务(Service)的工作原理及其与Activity间的通信方式,以及BroadcastReceiver广播接收器的使用方法。
摘要由CSDN通过智能技术生成

一、线程和Handler异步消息机制

1.1 线程与主线程

线程是一个单一的执行序列。单个线程中的代码可得到逐步执行。每个Android应用的运行都是从主线程开始的。然而,主线程并非如线程般的预定执行序列,如下图。相反,它处于一个无限循环的运行状态,等待着用户或系统触发事件的发生。事件触发后,主线程便负责执行代码,以响应这些事件。


注意:如果想要更新应用程序里的 UI 元素,则必须在主线程中进行,否则就会出现异常;而主线程不能执行网络连接等耗时行为,等待响应的时候,用户界面将会毫无反应,这可能会导致应用无响应(ANR:Application Not Responding),我们用子线程来实现耗时行为。

1.2 线程的基本用法

  1. 定义一个线程只需要新建一个类继承自 Thread,然后重写父类的 run()方法,并在里面编写耗时逻辑即可;
class MyThread extends Thread {

    @Override
    public void run() {
    // 处理具体的逻辑
    }
}

启用线程,只需要 new 出 MyThread 的实例,然后调用它的 start()方法,这样 run()方法中的代码就会在子线程当中运行了;

new MyThread().start();
2. 为了降低耦合度,我们经常使用实现Runnable()接口的方式来定义一个线程:
class MyThread implements Runnable {

    @Override
    public void run() {
        //处理具体的逻辑
    }
}
启用方法也有所调整:

MyThread myThread = new MyThread();
new Thread(myThread).start();
3.  如果不想专门再定义一个类去实现 Runnable 接口,也可以使用匿名类的方式,这种写法更为常见,如下所示:
    new Thread(new Runnable() {

        @Override
        public void run() {
        // 处理具体的逻辑
        }
    }).start();

1.3 异步消息处理机制

1.3.1 四个概念

1. message : 它是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。
消息是message的一个实例,它有一下三个要素:
◆what— 用户定义的int型消息代码,用来描述消息;
◆obj — 随消息发送的用户指定对象;
◆target — 处理消息的Handler。
2.message queue

MessageQueue 是消息队列的意思,它主要用于存放所有通过 Handler 发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个MessageQueue 对象。

3.looper

Looper 是每个线程中的 MessageQueue 的管家,调用 Looper 的 loop()方法后,就会进入到一个无限循环当中,然后每当发现 MessageQueue 中存在一条消息,就会将它取出,并传递到 Handler 的 handleMessage()方法中。每个线程中也只会有一个Looper 对象。

主线程也是一个消息循环,因此具有一个looper。主线程的所有工作都是由其looper完成的。

4.Handler:

Handler 顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用 Handler 的 sendMessage()方法,而发出的消息经过一系列地辗转处理后,最终会传递到 Handler 的 handleMessage()方法中。


Looper、Handler、Message和HandlerThread的关系


1.3.2 使用方法

public class MainActivity extends Activity {

    public static final int MASSAGE_CODE = 00001;
    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
//            接收message
            switch (msg.what) {
                case MASSAGE_CODE:
                    int value = (int) msg.obj;
                    mTextView.setText(String.valueOf(value / 1000));

                    msg = Message.obtain();
                    msg.arg1 = 0;
                    msg.arg2 = 1;
                    msg.what = MASSAGE_CODE;
                    msg.obj = value - 1000;
//<span style="white-space:pre">	</span>循环发送massage
                    if (value > 0) {
                        sendMessageDelayed(msg, 1000);
                    }
                    break;
            }
        }
    };
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activiyt_handler);
        mTextView = (TextView) findViewById(R.id.handler_textView);

        Message message = mHandler.obtainMessage();

        message.arg1 = 0;
        message.arg2 = 1;
//what在这里是相当于一个标牌,用于区别不同的message,可转成常量
        message.what = MASSAGE_CODE;
        message.obj = 10000;
//发送message
        mHandler.sendMessageDelayed(message, 1000);
    }
}
  1. 首先创建一个Handler实例,实现其继承的方法 handleMessage(Message msg) ,在方法中接收并处理message,并将处理完的message发送出去,完成一个循环机制的代码;
  2. 在onCreate()方法中,使用Handler.obtainMessage(...)方法创建(拉取)一个消息实例,在以创建的Handler中完成Handler操作。

二、服务(Service)

2.1 定义一个服务

public class MusicService extends Service {

    private MediaPlayer mMediaPlayer;

    @Override
    public void onCreate() {
        super.onCreate();
        mMediaPlayer = MediaPlayer.create(this, R.raw.shalong);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mMediaPlayer.start();
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mMediaPlayer.stop();
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
最常见的三种方法:
onCreat() —— 在服务第一次创建的时候调用;
onStartCommand() —— 在每次服务启动的时候调用,如果希望服务一旦启动就立刻去执行某个操作,就将逻辑写在这个方法里;
onDestroy() —— 在服务销毁的时候调用,而当服务销毁时,我们又应该在 onDestroy()方法中去回收那些不再使用的资源;
另外,每一个服务都需要在 AndroidManifest.xml 文件中进行注册才能生效,这是 Android 四大组件共有的特点。

2.2 Service和Activity之间的通信——binder

上面的代码中,创建了一个MusicService类,其中onBind()是唯一的一个抽象方法,所以必须要在子类中实现。 它用来实现Service和Activity之间的通信。

比如说目前我们希望在 MyService 里提供一个下载功能,然后在活动中可以决定何时开始下载,以及随时查看下载进度。实现这个功能的思路是创建一个专门的 Binder 对象来

对下载功能进行管理。

@Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //在这里返回新创建的LocalBinder实例
        return mLocalBinder;
    }

    public class LocalBinder extends Binder {
        //可以获取进度的Binder
        public int getProgress() {
            return 0;
        }
    }

    LocalBinder mLocalBinder = new LocalBinder();
上面的代码中,我们新建了一个 DownloadBinder 类,并让它继承自 Binder,然后在它的内部提供了开始下载以及查看下载进度的方法。接着,在 MyService 中创建了 DownloadBinder 的实例,然后在 onBind()方法里返回了这个实例,这样 MyService 中的工作就全部完成了。


接下来,添加在MainActivity中的代码:

  1. 首先创建一个ServiceConnection的匿名类,在里面重写onServiceConnected()和onServiceDisconnected()方法。这两个方法分别会在活动与服务成功绑定以及解除绑定的时候调用。
  2. 在 onServiceConnected()方法中,我们又通过向下转型得到了 LocalBinder 的实例,有了这个实例,活动和服务之间的关系就变得非常紧密了。现在我们可以在活动中根据具体的场景来调用 LocalBinder 中的任何 public 方法,即实现了指挥服务干什么,服务就去干什么的功能

  3. 调用bindService()方法将 MainActivity 和MusicService 进行绑定。bindService()方法接收三个参数,第一个参数就是刚刚构建出的 Intent 对象,第二个参数是前面创建出的ServiceConnection 的实例,第三个参数则是一个标志位,这里传入BIND_AUTO_CREATE 表示在活动和服务进行绑定后自动创建服务。这会使得 MyService中的 onCreate()方法得到执行,但 onStartCommand()方法不会执行。调用一下 unbindService()方法解绑。


三、BroadReceiver — 广播接收器

静态注册:注册之后是一直有效的(可用于开机启动)。

使用方法:在mainfest中注册receiver,在程序代码中触发动作发送广播,receiver接收广播,并根据类中定义的逻辑代码进行操作。

动态注册:用完之后还要销掉,要有onStart、onStop函数进行注册和反注册操作。

使用方法:在程序代码中注册receiver,并触发动作发送广播,receiver接收广播,并根据类中定义的逻辑代码进行操作。


广播类型——Normal Broadcasts(标准广播):是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。


Ordered Broadcasts(有序广播):是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的广播接收器就无法收到广播消息了。通过 mainfest中的android:priority 属性给广播接收器设置了优先级,优先级比较高的广播接收器就可以先收到广播。



广播又分为系统广播和自定义广播:系统广播 —— 是系统发出的广播,有系统默认值的广播,需要在mainfest中声明使用权限,否则程序将会直接崩溃;

自定义广播 —— 在文件中自定义一个带有一个值的广播,用来发送和接收。

本地广播 —— 使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播。


生命周期:register——> sendBroadcast ——> onReceice ——> unregister


拾遗:

1. binder粘合剂、 process进程、thread线程、component组件、flags标记、expoted输出、传播、interface接口、register登记、注册
2. 安卓四大组件:activity、service、provider、receiver,使用时需要在mainfest中声明。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值