Android(11)——Android四大组件

Android

安卓开发者指南:https://developer.android.google.cn/guide

Android四大组件

Android常用四大组件:
1.Activity
2.Service
3.Content provider
4.Broadcast receiver

1 Activity

(1)一个Activity通常就是一个单独的屏幕(窗口)。
(2)Activity之间通过Intent进行通信。
(3)android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity。
之前的文章也有讲到,回头了解:https://blog.csdn.net/weixin_45044097/article/details/106695692

2 Service

(1)service用于在后台完成用户指定的操作。service分为两种:
(a)started(启动):当应用程序组件(如activity)调用startService()方法启动服务时,服务处于started状态。
(b)bound(绑定):当应用程序组件调用bindService()方法绑定到服务时,服务处于bound状态。

(2)startService() 与 bindService()区别:
(a)started service(启动服务)是由其他组件调用startService()方法启动的,这导致服务的onStartCommand()方法被调用。当服务是started状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此,服务需要在完成任务后调用stopSelf()方法停止,或者由其他组件调用stopService()方法停止。
(b)使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。

(3)开发人员需要在应用程序配置文件中声明全部的service,使用< service>< /service>标签。
(4)Service通常位于后台运行,它一般不需要与用户交互,因此Service组件没有图形用户界面。Service组件需要继承Service基类。Service组件通常用于为其他组件提供后台服务或监控其他组件的运行状态。
来源:https://blog.csdn.net/ican87/article/details/21874321
这部分有个大概了解,之后再补充…

3 Content provider

(1)android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过ContentResolver类从该内容提供者中获取或存入数据。

(2)只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式。

(3)ContentProvider实现数据共享。ContentProvider用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,因为android没有提供所有应用共同访问的公共存储区。

(4)开发人员不会直接使用ContentProvider类的对象,大多数是通过ContentResolver对象实现对ContentProvider的操作。

(5)ContentProvider使用URI来唯一标识其数据集,这里的URI以content://作为前缀,表示该数据由ContentProvider来管理。

来源:https://blog.csdn.net/ican87/article/details/21874321
这部分有个大概了解,之后再补充…

4 Broadcast receiver

4.1 概述

广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”。
普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播;
有序广播是按照接收者声明的优先级别(声明在intent-filter元素的android:priority属性中,数越大优先级别越高,取值范围:-1000到1000。也可以调用IntentFilter对象的setPriority()进行设置),被接收者依次接收广播。如:A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C。A得到广播后,可以往广播里存入数据,当广播传给B时,B可以从广播中得到A存入的数据。

作者:Lemon_95
链接:https://www.jianshu.com/p/51aaa65d5d25
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

(1)你的应用可以使用它对外部事件进行过滤,只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activity或serice来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力,例如闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
(2)广播接收者的注册有两种方法,分别是程序动态注册和AndroidManifest文件中进行静态注册。
(3)动态注册广播接收器特点是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。

广播分为两个角色:广播发送者、广播接受者

android 广播:
1)用于不同组件间的通信(含:应用内/不同应用之间)
2)用于多线程通信
3)与android系统的通信

观察者模式,广播的机制:
在这里插入图片描述

4.2 生命周期

1.onReceive()
2.执行线程
3.执行时间限制

如果一个广播处理完onReceive 那么系统将认定此对象将不再是一个活动的对象,也就会finished掉它。

注意 :BroadcastReceiver生命周期很短,如果需要在onReceiver完成一些耗时操作,应该考虑在Service中开启一个新线程处理耗时操作,不应该在BroadcastReceiver中开启一个新的线程,因为BroadcastReceiver生命周期很短,在执行完onReceiver以后就结束,如果开启一个新的线程,可能出现BroadcastRecevier退出以后线程还在,而如果BroadcastReceiver所在的进程结束了,该线程就会被标记为一个空线程,根据Android的内存管理策略,在系统内存紧张的时候,会按照优先级,结束优先级低的线程,而空线程无异是优先级最低的,这样就可能导致BroadcastReceiver启动的子线程不能执行完成。

4.3 广播接收器注册

注册的方式有两种:
➢静态注册:AndroidManifest.xml,8.0之后静态注册的限制
➢动态注册:Java code

系统广播
1.常见的系统广播:开机广播、网络状态、电池变化
2.发起者
3.接收者
4.使用步骤:注册+接收+使用
5.演示(系统广播+动态注册)

如果要进行的操作需要花费比较长的时间,则不适合放在BroadcastReceiver中进行处理。
在 Android 中,程序的响应( Responsive )被活动管理器( Activity Manager )和窗口管理器( Window Manager )这两个系统服务所监视。当 BroadcastReceiver 在 10 秒内没有执行完毕,Android 会认为该程序无响应。所以在 BroadcastReceiver 里不能做一些比较耗时的操作,否侧会弹出ANR ( Application No Response )的对话框。如果需要完成一项比较耗时的工作,应该通过发送Intent 给 Service ,由 Service 来完成。而不是使用子线程的方法来解决,因为 BroadcastReceiver 的生命周期很短(在 onReceive() 执行后 BroadcastReceiver 的实例就会被销毁),子线程可能还没有结束BroadcastReceiver 就先结束了。如果 BroadcastReceiver 结束了,它的宿主进程还在运行,那么子线程还会继续执行。但宿主进程此时很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。

4.3.1 静态注册

注册方式:在AndroidManifest.xml 里通过< receiver> 标签声明:

<receiver
	//继承BroadcastReceiver子类的类名
    android:name=".mBroadcastReceiver"
	android:enable="true"/"false"
	//此broadcastReceiver 是否接受其他应用发出的广播
	//默认值时由receiver 中d有无inter-filter决定,如果有,默认true,否则默认false
	android:exported="true"/"false"
	android:icon="drawable resource"
	android:label="string resource"
	//具有相应权限的广播发送者发送的广播才能被此BroadcastReceiver所接收;
    android:permission="string"
	//BroadcastReceiver运行所处的进程
	//默认为app的进程,可以指定独立的进程
	//注:Android四大基本组件都可以通过此属性指定自己的独立进程
    android:process="string" >
	//用于指定此广播接收器将接收的广播类型
	 <intent-filter>
	 	// 开机广播
	 	<action android:name="android.intent.action.BOOT_COMPLETED"/>
	 	// 电量低广播
	 	<action android:name="android.intent.action.BATTERY_LOW"/>
	 	//接收网络状态改变时发出的广播
		<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
	 	// 应用被安装广播
	 	<action android:name="android.intent.action.PACKAGE_INSTALL"/>
	 	// 应用被卸载广播
	 	<action android:name="android.intent.action.BOOT_REMOVE"/>
	 	// 数据类型
	 	<data android:scheme="package"/>
	 </intent-filter>
 </receiver>

步骤:
1,自定义一个类继承BroadcastReceiver
2,重写onReceive方法
3,在manifest.xml中注册

public class ImBroadcastReceiver extends BroadcastReceiver{
	private static final String TAG = "ImBroadcastReceiver";
	@Override
	public void onReceive(Context context, Intent intent) {
		// 接收广播
		if(intent != null) {
			// 接收到的是什么广播
			String action = intent.getAction();
			Log.d(TAG,"onReceive: " + action);
		}
	}
}
4.3.2 动态注册

注册方式:在代码中调用Context.registerReceiver() 方法,不需要在AndroidManifest.xml中声明。

特别注意
动态广播最好在onResume中注册, onPause注销
原因:
1、对于动态广播,有注册必然得有注销,否则会导致内存泄漏
2、onPause在App死亡前一定会被执行,从而保证app死亡前一定会被注销,从而防止内存泄漏

特别注意:
对于不同注册方式的广播接收器回调OnReceive(Context context,Intent intent)中的context返回值是不一样的:
对于静态注册(全局+应用内广播),回调onReceive(context, intent)中的context返回值是:ReceiverRestrictedContext;
对于全局广播的动态注册,回调onReceive(context, intent)中的context返回值是:ActivityContext;
对于应用内广播的动态注册(LocalBroadcastManager方式),回调onReceive(context, intent)中的context返回值是:Application Context。
对于应用内广播的动态注册(非LocalBroadcastManager方式),回调onReceive(context, intent)中的context返回值是:Activity Context;

4.3.3 区别

静态注册和动态注册区别

动态注册广播不是常驻型广播,也就是说广播跟随activity的生命周期。注意: 在activity结束前,移除广播接收器。
静态注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
当广播为有序广播时:
1 优先级高的先接收
2 同优先级的广播接收器,动态优先于静态
3 同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。
当广播为普通广播时:
1 无视优先级,动态广播接收器优先于静态广播接收器
2 同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。

广播的发送 = 广播发送者将此广播的意图(intent)通过 sendBroasdcast() 方法发送出去广播的类型。

普通广播、系统广播、有序广播、粘性广播、App应用内广播

4.4 自定义广播

与系统广播的区别:发起者、接受者不同

步骤:继承BroadcastReceiver 基类;必须重写抽象方法onReceive()方法

演示一(自定义广播+动态注册)
在这里插入图片描述
在这里插入图片描述
intentFilter.addAction(MY_ACTION)中String MY_ACTION="com.imooc.demo.adsd;"自定义的

演示二(两个应用,一个发送,一个接收):APP间的广播

1,广播接收器收到相应广播后,会自动调用onReceive() 方法
2,一般情况下,onReceive方法会会涉及与其他组件之间的交互,如 发送Notiotification,启动server等
3,默认情况下,广播接收器运行在UI线程,因此,onReceive方法不能执行耗时操作,否则将导致ANR

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章