当前位置:   article > 正文

Android四大基本组件详解-Activity,BroadcastReceiver,Service及ContentProvicer_activity(活动)、service(服务)、broadcoast receiver(广播接收者

activity(活动)、service(服务)、broadcoast receiver(广播接收者)、content prov

一,活动(Activity)

1.简介

应用程序中,一个Activity通常就是一个单独的屏幕。每个Activity都被实现为一个独立的类,并且从Activity基类继承而来, Activity类会提供视图控制组件的用户接口,并对事件作出响应。

2.任务栈

在这里插入图片描述
Android应用可能含有多个Activity,需要借助Activity活动栈机制来管理这些Activity之间的先后次序关系
①任务栈用来存放用户开启的Activity。
②在应用程序创建之初,系统会默认分配给其一个任务栈(默认一个),并存储根Activity。
③同一个Task Stack,只要不在栈顶,就是onStop状态
④任务栈的id自增长型,是Integer类型。
⑤新创建Activity会被压入栈顶。点击back会将栈顶Activity弹出,并产生新的栈顶元素作为显示界面(onResume状态)。
⑥当Task最后一个Activity被销毁时,对应的应用程序被关闭,清除Task栈,但是还会保留应用程序进程,再次点击进入应用会创建新的Task栈

3.Activity的4种状态

状态名解释举例
活动状态当前Activity在Activity活动栈中处于最上层完全能被用户看到,并能够与用户进行交互正在运行的屏幕
暂停状态当前Activity在界面上被部分遮挡(以对话框形式展示),不再处于用户界面的最上层,不能够与用户进行交互启动一个新的Activity
停止状态Activity在界面上完全不能被用户看到,也就是说这个Activity被其他Activity全部遮挡用户按下“Home”键时
非活动状态不在以上三种状态中的Activity,处于非活动状态被销毁的Activity

4. 7种生命周期方法

在这里插入图片描述
在这里插入图片描述

5.Activity的四种启动模式

(1)Standard 标准模式(默认启动模式)

该模式可以被设定,不在manifest设定时候,Activity的默认模式就是standard。在该模式下,启动的Activity会依照启动顺序被依次压入Task中:
在这里插入图片描述

(2)SingleTop 栈顶模式(栈顶复用模式)

在该模式下,如果栈顶Activity为我们要新建的Activity(目标Activity),那么就不会重复创建新的Activity。
在这里插入图片描述
代码示例:

<activity android:name=".TwoActivity"
          android:launchMode="singleTop">
         <intent-filter>
             <action android:name="ONETEXT_TWOACTIVITY" />
             <category android:name="android.intent.category.DEFAULT" />
         </intent-filter>
</activity>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

(3)SingleTask 单任务模式(栈内复用模式)

与singleTop模式相似,只不过singleTop模式是只是针对栈顶的元素,而singleTask模式下,如果task栈内存在目标Activity实例,则:

①将task内的对应Activity实例之上的所有Activity弹出栈。
②将对应Activity置于栈顶,获得焦点。
在这里插入图片描述

(4)SingleInstance 单实例模式(全局唯一模式)

在该模式下,我们会为目标Activity分配一个新的affinity,并创建一个新的Task栈,将目标Activity放入新的Task,并让目标Activity获得焦点。新的Task有且只有这一个Activity实例。 如果已经创建过目标Activity实例,则不会创建新的Task,而是将以前创建过的Activity唤醒
在这里插入图片描述
• 小试牛刀:

问题:A、B、C、D分别是四种Activity的启动模式,那么A- >B->C->D->A->B->C->D分别启动,最后的activity栈是怎么样的?

答案:两个栈,前台栈是只有D,后台栈从底至上是A、B、C。

6.谈谈onSaveInstanceState()方法?何时调用

Activity意外销毁时再重建时会调用此方法,比如横竖屏切换会导致重建Activity,onSaveInstanceState()方法的调用在onStop()之前,用于保存当前Activity的状态,当Activity被重新创建后,会调用onRestoreInstanceState()来恢复Activity的状态,onRestoreInstanceState()的调用在onStart()之前。

onSaveInstanceState()执行场景:

  1. 当用户按下HOME键时
  2. 长按HOME键,选择运行其他的程序时
  3. 锁屏时
  4. 从activity A中启动一个新的activity时
  5. 屏幕方向切换时

二,广播消息接收器(BroadcastReceiver

1.概念

BroadcastReceiver是Android系统中常用的一种机制,用户让应用对一个外部的事件作出响应

2.举个栗子

例如:①开机的时候,系统会进行一个全局广播,消息是按开机了,这时候有广播接收者接到了这个消息,就会相应启动一些程序或服务,实现开机启动。
②还有就是你的网络出了问题,比如网络断开了,链接到wifi之类,或者还有电量改变,收发短信都会发出广播,这时候有对应的程序来反应。

3.重要性及适用场景

可能觉得BroadcastReceiver没有大的用处,可能因为你现在的程序还没有用到关于系统事件所对应的反应,但这不代表BroadcastReceiver是不重要的。

平时在开发过程中遇到的单进程多线程通信的场景比较多,所以这种情况下使用BroadcastReceiver并不是最佳选择,很多人会自己实现一套Observer 或者使用EventBus等第三方库来完成该功能,不可否认,他们在这种场合下不论是效率还是灵活性方面都更具优势。

但是,BroadcastReceiver既然能够在Android四大组件中占有一席之地,自然也有它独有的优势,系统相关事件的监听,比如开机启动,网络连接,电量变化等。多进程通信,这些是Observer 或者EventBus很难办到的。

所以BroadcastReceiver的使用需要看具体的使用场景,像单进程多线程这种场景,就不建议用BroadcastReceiver了,有种杀鸡用牛刀的感觉,使用Observer 或者EventBus更适合;但是对于需要监听系统广播事件的场合,例如现在很多进程保活机制里面就用到了一些系统广播的监听,就正是BroadcastReceiver大展拳脚的时候了。

4.无序广播与有序广播代码实现

(1)发送自定义的无序广播

①发送广播

public void startBroadcast(View view){
        //开启广播
        //创建一个意图对象
        Intent intent = new Intent();
        //指定发送广播的频道
        intent.setAction("com.example.BROADCAST");
        //发送广播的数据
        intent.putExtra("key", "发送无序广播,顺便传递的数据");
        //发送
        sendBroadcast(intent);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

②接收广播
新建一个类,继承BroadcastReceiver(类比于购买了一个收音机)

public class UnorderedReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        String data = intent.getStringExtra("key");

        System.out.println("接受到了广播,action:"+ action +",data:"+data);

        //接受到了广播,action:com.example.BROADCAST,data:发送无序广播,顺便传递的数据
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

③在清单文件中进行注册

<!-- 相当于装电池 -->
<receiver android:name="com.example.selfreceiver.UnorderedReceiver">
		<!-- 相当于调频道 -->
       <intent-filter>
         <action android:name="com.example.BROADCAST"/>
     </intent-filter>
</receiver>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

④运行结果
在这里插入图片描述

(2)发送自定义的有序广播

1)发送广播

// 发送有序广播
    public void sendOrderedBroad(View view) {
        Intent intent = new Intent();
        intent.setAction("com.example.ORDERED");
        // 发送无序广播
        sendOrderedBroadcast(intent,//意图动作,指定action动作
                null, //receiverPermission,接收这条广播具备什么权限
                new FinalReceiver(),//resultReceiver,最终的广播接受者,广播一定会传给他
                null, //scheduler,handler对象处理广播的分发
                0,//initialCode,初始代码
                "每人发10斤大米,不得有误!", //initialData,初始数据
                null//initialExtras,额外的数据,如果觉得初始数据不够,可以通过bundle来指定其他数据
                );
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在上面的代码中,广播发送者发送了一条广播:“每人发10斤大米,不得有误!”

2)接收广播
新建一个类, 继承BroadcastReceiver,并在清单文件中进行注册
以下是所有的广播接收者在清单文件中的注册
在这里插入图片描述
权限从-1000 至 1000
权限高的广播接收者可以修改广播,甚至可以终止广播
权限高的广播接收者1:

public class ShengReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        //获取广播的数据
        String data = getResultData();

        //修改
        setResultData("中央下达福利,每人5斤大米");

        System.out.println("省政府收到指示, data : "+data);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在这里, 这个接收者修改广播为: “中央下达福利,每人5斤大米”

权限低的广播接收者

public class PeopleReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //获取广播的数据
        String data = getResultData();
        System.out.println("老百姓收到福利,感谢党, data : "+data);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这样,在控制台打印出来的信息为:
在这里插入图片描述
权限低的接收者 接收到的广播就是修改后的了

②终止广播

权限高的广播接收者:

public class ShengReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        //获取广播的数据
        String data = getResultData();

        //也可以终止广播,权限小的接收者就接收不到广播了
        abortBroadcast();

        System.out.println("省政府收到指示, data : "+data);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

控制台打印:
在这里插入图片描述
权限小的就接收不到广播了…
③resultReceiver
可以在广播发送者的应用中建一个resultReceiver, 用于接收最终到达的广播,
无论广播是否终止,都会被resultReceiver接收

public class FinalReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String resultData = getResultData();
        System.out.println("人民收到的最终福利是: "+ resultData);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

控制台打印信息:

(终止广播后):
在这里插入图片描述(修改广播后):
在这里插入图片描述

5.有序广播和无序广播的区别:

(1)无序广播:发送方发出后,几乎同时到达多个广播接收者处,某个接收者不能接收到广播后进行一番处理后传给下一个接收者,并且无法终止广播继续传播;

Context.sendBroadcast(intent);

(2)有序广播:广播接收者需要提前设置优先级,优先级高的先接收到广播,优先级数值为-1000~1000,在AndroidManifest.xml的设置;比如存在3个广播接收者A、B、C,优先级A>B>C,因此A最先收到广播,当A收到广播后,可以向广播中添加一些数据给下一个接收者(intent.putExtra()),或者终止广播(abortBroadcast());

Context.sendOrderedBroadcast(intent);

三,服务(Service)

1.概念

一个服务是具有一个较长生命周期且没有用户界面的程序。例如:一个正在从播放列表中播放歌曲的媒体播放器。

2.启动Service(两种方式)

(1)使用startService()方法启动Service,调用者与Service之间没有关系,即使调用者退出了,Service仍然运行。Service不会自动销毁,需要外部调用stopService()方法或在Service内部调用stopSelf()方法,此时Service的onDestroy()方法被调用。
(2)使用bindService()方法启动Service,调用者与Service绑定在了一起,调用者一旦销毁,Service也就终止了,调用者需要解绑时可调用unBindService()方法。Service被解绑或调用者销毁时,Service经历onUnbind() > onDestroy()的过程。

四,内容提供者(ContentProvicer)

– 应用程序能够将它们的数据保存到文件、SQLite数据库中,甚至是任何有效的设备中。当需要将当前应用数据与其它应用共享时,ContentProvider类实现了一组标准方法,从而能够让其它的应用保存或读取此ContentProvider处理的各种数据类型。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/936720
推荐阅读
相关标签
  

闽ICP备14008679号