Service、Broadcast、ContentProvider简要介绍和使用

一、Service简介:

1.可以让程序在后台一直做它想要做的事情,即使当前没有与用户进行交互。(对应context.startService()的启动方式)。 

2.实现了某些功能已供其他程序调用的工具,并可保持长期连接进行交互。(对应context.bindService()的启动方式)。

二、Service生命周期

 onCreate () 首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或onBind() 之前)。如果服务已在运行,则不会调用此方法,该方法只调用一次  。

onBind(Intent intent) 当整个系统的内存不足,并且正在运行的进程应减少其内存使用量时,将调用此方法。尽管没有定义确切的调用点,但是通常会在杀死所有后台进程时发生。也就是说,在达到终止进程的目的之前,我们要避免终止承载服务和前台UI的进程。  您应该实现此方法以释放可能要保留的所有缓存或其他不必要的资源。从此方法返回后,系统将为您执行垃圾回收。 

onRebind(Intent intent) 仅当onUnbind(Intent)的实现被重写以返回true时,才调用此方法。 

onUnbind(Intent intent) 当所有客户端都与服务发布的特定接口断开连接时调用。 默认实现不执行任何操作,并返回false。 

onDestroy () 当运行的设备配置发生更改时,系统调用此方法。与Activity等其他组件不同,当这个回调发生时Service不会重走生命周期。

三、主要方法onStartCommand (Intent intent, int flags, int startId)

intent :启动时,启动组件传递过来的Intent,如Activity可利用Intent封装所需要的参数并传递给Service

flags:表示启动请求时是否有额外数据,可选值有 0,START_FLAG_REDELIVERY,START_FLAG_RETRY。

0代表没有。

START_FLAG_REDELIVERY 这个值代表了onStartCommand方法的返回值为 START_REDELIVER_INTENT,而且在上一次服务被杀死前会去调用stopSelf方法停止服务。其中START_REDELIVER_INTENT意味着当Service因内存不足而被系统kill后,则会重建服务,并通过传递给服务的最后一个 Intent 调用 onStartCommand(),此时Intent时有值的。

START_FLAG_RETRY 该flag代表当onStartCommand调用后一直没有返回值时,会尝试重新去调用onStartCommand()。

startId : 指明当前服务的唯一ID,与stopSelfResult (int startId)配合使用,stopSelfResult 可以更安全地根据ID停止服务。

返回值 :实际上onStartCommand的返回值int类型才是最最值得注意的,它有三种可选值, START_STICKY,START_NOT_STICKY,START_REDELIVER_INTENT,它们具体含义如下: START_STICKY 当Service因内存不足而被系统kill后,一段时间后内存再次空闲时,系统将会尝试重新创建此Service,一旦创建成功后将回调onStartCommand方法,但其中的Intent将是null,除非有挂起的Intent,如pendingintent,这个状态下比较适用于不执行命令、但无限期运行并等待作业的媒体播放器或类似服务。

START_NOT_STICKY 当Service因内存不足而被系统kill后,即使系统内存再次空闲时,系统也不会尝试重新创建此Service。除非程序中再次调用startService启动此Service,这是最安全的选项,可以避免在不必要时以及应用能够轻松重启所有未完成的作业时运行服务。

START_REDELIVER_INTENT 当Service因内存不足而被系统kill后,则会重建服务,并通过传递服务的最后一个 Intent 调用 onStartCommand(),任何挂起 Intent均依次传递。与START_STICKY不同的是,其中的传递的Intent将是非空,是最后一次调用startService中的intent。这个值适于主动执行应该立即恢复的作业(例如下载文件)的服务。   

四、Service的使用

1.首先我们需要创建一个继承了android.app.Service的类。

2.AS通常会在我们创建service类后自动在清单文件内加入service的声明,若没有的话就需要我们手动添加。 

<service android:name=".TestService"/> 

android:exported:代表是否能被其他应用隐式调用,其默认值是由service中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。为false的情况下,即使有intent-filter匹配,也无法打开,即无法被其他应用隐式调用。

android:name:对应Service类名

android:permission:是权限声明

android:process:是否需要在单独的进程中运行,当设置为android:process=”:remote”时,代表Service在单独的进程中运行。注意“:”很重要,它的意思是指要在当前进程名称前面附加上当前的包名,所以“remote”和”:remote”不是同一个意思,前者的进程名称为:remote,而后者的进程名称为:App-packageName:remote。

android:isolatedProcess :设置 true 意味着,服务会在一个特殊的进程下运行,这个进程与系统其他进程分开且没有自己的权限。与其通信的唯一途径是通过服务的API(bind and start)。

android:enabled:是否可以被系统实例化,默认为 true因为父标签 也有 enable 属性,所以必须两个都为默认值 true 的情况下服务才会被激活,否则不会激活。

3.在activity或其他上下文中启动service

启动服务  startService(new Intent(this, TestService.class));  绑定服务    

    //创建一个ServiceConnection,可以在回调方法中进行逻辑处理
    private Myconnection mConnection;
    class Myconnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected ComponentName : " + name + " IBinder : " + service);
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected ComponentName : " + name);
        }
    }
    //绑定服务
    bindService(new Intent(this, TestService.class), mConnection, Context.BIND_AUTO_CREATE);

 解绑服务  unbindService(mConnection); 

停止服务  stopService(new Intent(this, TestService.class));

一、Broadcast介绍

        是一个全局的监听器,属于Android四大组件之一      Broadcast(广播)是一种广泛运用的在应用程序(APP)之间传输信息的机制。而BroadcastReceiver(广播接收器)是对发送出来的 广播进行过滤接受并响应的一类组件。作用:监听 / 接收 应用发出的广播消息,并做出响应。

原理描述

  1. 广播接收者通过Binder机制在AMS注册
  2. 广播发送者通过Binder机制向AMS发送广播
  3. AMS根据广播发送者的要求,在注册列表中,查找合适的广播接收者
  4. AMS将广播发送到对应的广播接收者的消息循环队列中
  5. 广播接收者通过消息循环拿到广播,并回调onReceive()

生命周期:BroadcastReceiver 生命周期非常短暂,发送广播时创建,onReceive()方法结束之后销毁

 三要素

  1. Broadcast (广播) --  用于发送广播
  2. BroadcastReceiver (广播接收器) --  用于接受广播
  3. Intent (意图) -- 用于保存广播相关信息的媒介     

两个重要的步骤: 1、创建广播接收器;2、注册广播接收器

二、区别

发送分类:标准广播(所有的都可以同时收到)、有序广播(有先后顺序的收到,受优先级影响)

接收分类:静态广播(在AndroidManifest.xml中注册的,不受任何组件的生命周期影响)、动态广播(在代码中注册的,跟随组件的生命周期的变化而变化)

三、静态广播

在项目右键 New --> Other -->Broadcast ,直接创建,在AndroidManifest.xml中已完成注册。

主函数下,按钮点击事件:

btn = findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        //整个包下都可以收到
        intent.setPackage(getPackageName());
        //仅当前类实现
        //intent.setComponent(new ComponentName(getPackageName(),"com.example.broadcasttest.MyReceiver"));
        intent.putExtra("name", "小黑");
        intent.putExtra("strs", arry);
        sendBroadcast(intent);
    }
});

自定义静态广播接收器

public class MyReceiver extends BroadcastReceiver {
    private static final String TAG = "MyReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        String name = intent.getStringExtra("name");
        String[] strs = intent.getStringArrayExtra("strs");
        Log.d(TAG, "onReceive: " + name + "---" + strs);
    }
}

四、动态广播

1、先自定义一个类继承BroadcastReceiver类:

public class TestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "接收到动态广播", Toast.LENGTH_SHORT).show();
    }
}

2、在代码内部注册动态广播:

//注册动态广播
mTestReceiver = new TestReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.broadcast.action.test");
registerReceiver(mTestReceiver, filter);

3、按钮事件发送广播:

btn = findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        intent.setAction("android.broadcast.action.test");
         intent.putExtra("name", "小黑");
        intent.putExtra("strs", arry);
        sendBroadcast(intent);
    }
});

动态广播的反注册

@Override
protected void onDestroy() {
    super.onDestroy();
    //反注册,在活动销毁时,解除注册
    unregisterReceiver(mTestReceiver);
}

onCreate() - onDestroy()(即便页面未显示,仍然能接受广播)

onResume() - onPause() (即只有页面显示时,才能接受广播)

onStart () - onStop()

注:注册与反注册广播方法要成对出现,重复注册、重复注销也不允许

注:调用Context注册,就要用Context反注册。而不能直接调用unregisterReceiver(mReceiver)

一、ContentProvider简介

        ContentProvider的作用是为不同的应用之间数据共享,提供统一的接口,我们知道安卓系统中应用内部的数据是对外隔离的,要想让其它应用能使用自己的数据(例如通讯录)这个时候就用到了ContentProvider。ContentProvider通过uri来标识其它应用要访问的数据,通过ContentResolver的增、删、改、查方法实现对共享数据的操作。还可以通过注册ContentObserver来监听数据是否发生了变化来对应的刷新页面。

进程间 进行数据交互 & 共享,即跨进程通信,数据源可以是数据库、文件、XML、网络等。

 二、关于URI和MIMRE类型数据

 

// 设置URI
Uri uri = Uri.parse("content://com.carson.provider/User/1") 
// 上述URI指向的资源是:名为 `com.carson.provider`的`ContentProvider` 中表名 为`User` 中的 `id`为1的数据

// 特别注意:URI模式存在匹配通配符* & #

// *:匹配任意长度的任何有效字符的字符串
// 以下的URI 表示 匹配provider的任何内容
content://com.example.app.provider/* 
// #:匹配任意长度的数字字符的字符串
// 以下的URI 表示 匹配provider中的table表的所有行
content://com.example.app.provider/table/# 

MIME作用:指定某个扩展名的文件用某种应用程序来打开

MIME组成:MIME = 类型 + 子类型

类型:单条记录 :vnd.android.cursor.item/自定义

多条记录(集合):vnd.android.cursor.dir/自定义

vnd:表示父类型和子类型具有非标准的、特定的形式。父类型已固定好(即不能更改),只能区别是单条还是多条记录。子类型可自定义。

三、ContentProvider讲解

问:为什么要使用通过ContentResolver类从而与ContentProvider类进行交互,而不直接访问ContentProvider类?

一般来说,一款应用要使用多个ContentProvider,若需要了解每个ContentProvider的不同实现从而再完成数据交互,操作成本高 & 难度大,所以再ContentProvider类上加多了一个 ContentResolver类对所有的ContentProvider进行统一管理。

ContentProvider是一个抽象类,如果我们需要开发自己的内容提供者我们就需要继承这个类并复写其方法,需要实现的主要方法如下:

  • public boolean onCreate() 在创建ContentProvider时使用
  • public Cursor query() 用于查询指定uri的数据返回一个Cursor
  • public Uri insert() 用于向指定uri的ContentProvider中添加数据
  • public int delete() 用于删除指定uri的数据
  • public int update() 用户更新指定uri的数据
  • public String getType() 用于返回指定的Uri中的数据MIME类型

数据访问的方法insert,delete和update可能被多个线程同时调用,此时必须是线程安全的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值