【Android】四大组件(Activity、Service、Broadcast Receiver、Content Provider)、结构目录

news2024/11/16 17:36:36

文章目录

    • Android系统架构
    • Android四大组件
      • Activity
      • Service
      • Broadcast Receiver
      • Content Provider
    • 两大视图
    • 主要结构目录

Android系统架构

https://blog.csdn.net/xzzteach/article/details/140904613

Android四大组件

Activity

  1. 一个 Activity 包含了用户能够看到的界面,从而于用户进行交互。一个应用程序中可以有零个或者多个Activity。零个 Activity 就表示,这个应用程序不包含与用户交互的界面。
  2. Android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明注册,否则系统将不识别也不执行该Activity。
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

在这里插入图片描述

  • Activity的生命周期
    Android 是使用任务(task)来管理Activity的,一个任务就是一组存放在栈里Activity的集合,这个栈也叫作返回栈。Activity的生命周期由以下几个部分组成:
函数描述
onCreat()一个Activity启动后第一个被调用的函数,常用来在此方法中进行Activity的一些初始化操作。例如创建View,绑定数据,注册监听,加载参数等。
onStart()当Activity显示在屏幕上时,此方法被调用但此时还无法进行与用户的交互操作。
onResume()英文词义简历、继续进行这个方法在onStart()之后调用,也就是在Activity准备好与用户进行交互的时候调用,此时的Activity一定位于Activity栈顶,处于运行状态。
onPause()这个方法是在系统准备去启动或者恢复另外一个Activity的时候调用,通常在这个方法中执行一些释放资源的方法,以及保存一些关键数据。
onStop()这个方法是在Activity完全不可见的时候调用的。
onDestroy()这个方法在Activity销毁之前调用,之后Activity的状态为销毁状态。
onRestart()当Activity从停止stop状态恢进入start状态时调用状态。

在这里插入图片描述
实际操作过程中,当打开启动Android应用时,MainActivity会经过onCreate-> onStart -> onResume三个阶段,此时若按home键或则back按键,MainActivity会经过onPause -> onStop这两个阶段,再进入此MainActivity时,会再调用onRestart -> onStart -> onResume三个阶段。

3、Activity 启动模式
启动模式一共有 4 中:standardsingleTopsingTasksingleInstance,可以在 AndroidManifest.xml 中通过 标签指定 android:launchMode 属性来选择启动模式。

standard模式

standard 模式是 Activity 的默认启动模式,在不进行显示指定的情况下,所有 Activity 都会自动使用这种启动模式。对于使用 standard 模式启动的 Activity,系统不会在乎这个 Activity 是否已经存在在栈中了。每次启动的时候都会创建一个新的实例。一般用于打开邮件之类的。
在这里插入图片描述

  • 下图为生成的默认Empty Activity

在这里插入图片描述

singleTop模式 (栈顶复用模式)

如果 Activity 指定为 singleTop,在启动 Activity 的时候发现返回栈的栈顶已经是该 Activity 了。则认为可以直接使用它,就不会再创建新的 Activity 实例了。因为不会创建新的 Activity 实例,所以 Activity 的生命周期就没有什么变化了。假设你在当前的Activity中又要启动同类型的Activity,此时建议将此类型Activity的启动模式指定为SingleTop,能够降低Activity的创建,节省内存!

一般用于登录页面,新闻详情页等。
在这里插入图片描述

singTask 模式(栈内单例模式)

singleTop 很好的解决了重复创建栈顶 Activity 的问题。如果 Activity 没有处于栈顶的位置,还是可能会创建多个 Activity 实例的。那就需要借助 singleTask 了。当 Activity 的启动模式为 singleTask 的时候,每次启动该 Activity 的时候系统会首先在返回栈中检查是否存在该 Activity 的实例,如果发现已经存在则直接使用该实例。并把这个 Activity 之上的所有 Activity 全部出栈,如果没有就会创建一个新的 Activity 实例。
一般主页面使用,购物页面,付款页面,浏览器主页等
在这里插入图片描述

  • 下图为uniapp
    在这里插入图片描述

singleInstance模式(堆内单例模式)

singleInstance 模式的 Activity 会启用一个新的返回栈来管理这个 Activity 。在这种模式下会有一个单独的返回栈来管理这个 Activity,不管是哪个应用程序来访问这个 Activity,都共用的同一个返回栈,也就解决了共享 Activity 实例的问题。

在这里插入图片描述

4、Activity 之间相互跳转及通信
Intent(意图)是应用程序种各个组件联系的桥梁,通信的载体,负责应用程序中数据的传递。

  • 不带数据跳转
Intent intent = new Intent(this,MainActivity.class);
startActivity(intent);

此段代码实现从当前Activity,跳转到MainActivity,不带任何参数。

  • 带数据或多个数据跳转
    //带数据跳转
String data = "是我主活动调用了你";
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("ext", data);
startActivity(intent);
  • 带数据跳转,带数据返回
Intent intent = new Intent(LoginActivity.this,RegisterActivity.class);
Bundle bundle = new Bundle() ;
bundle.putString("register","请开始注册!");
intent.putExtras(bundle) ;
startActivityForResult(intent,1);

在跳转时使用startActivityForResult方法,此方法传入两个参数一个是Intent ,另外一个是给当前请求设置的一个请求ID,此ID在结束数据时辨识是否使当前请求的返回结果。

同时要在跳转源Activity中实现 onActivityResult 方法来接收处理目的Activity返回的数据。

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case 1:
            if (resultCode == RESULT_OK) {
                final EditText loginUsername = findViewById(R.id.username);
                String returnUsername = data.getStringExtra("userName");
                //序列化方式取出实体
                User user = (User)data.getSerializableExtra("user");
                loginUsername.setText(returnUsername);
                loginUsername.setSelection(returnUsername.length());
            }
            break;
        default:
    }
}
  • Intent隐式实现启动其他程序Activity
    在当前Activity中调用百度请求界面。
Uri uri = Uri.parse("https://www.baidu.com");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);

直接调用打电话功能

Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("tel:13207690000"));
startActivity(i);

在使用系统电话功能时需要给当前应用程序授权,在AndroidManifest.xml文件中增加
<uses-permission android:name="android.permission.CALL_PHONE" />
打开地图界面

Uri uri = Uri.parse("geo:38.899533,-77.036476");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);

Service

  1. Service简单介绍
  • Service它可以在后台执行长时间运行操作而没有用户界面的应用组件,不依赖任何用户界面,例如后台播放音乐,后台下载文件等。
  • 虽然服务是在后台运行的,但是Service和Activity都是运行在当前APP所在的main thread(UI主线程)中的,而耗时操作(如网络请求、拷贝数据、大文件)会阻塞主线程,给用户带来不好的体验。如果需要在服务中进行耗时操作,可以选择 IntentService,IntentService是Service的子类,用来处理异步请求。
  1. Service启动的两种方式
  • startService()
    在Acitivity界面通过显式意图(或隐式意图)的方式来启动服务和关闭服务。
Intent intentService = new Intent(MainActivity.this, AudioServiceOnBind.class);
startService(intentService);

生命周期顺序:onCreate->onStartCommand->onDestroy

onCreate() 当Service第一次被创建时调用。

onStartCommand() 当startService方法启动Service时,该方法被调用。

onDestroy() 当Service不再使用时调用。

  • bindService()绑定服务
    当应用组件通过调用 bindService() 绑定到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果。 仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。

首先在我们的服务中创建一个内部类AudioBinder继承Binder来获取当服务实例,然后在onBind方法中返回当前服务的实例。

public class AudioServiceOnBind extends Service implements MediaPlayer.OnCompletionListener{
 
    private final IBinder binder = new AudioBinder();
    //用于播放音乐等媒体资源
    private MediaPlayer mediaPlayer;
    public AudioServiceOnBind() {
        super();
    }
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onStartCommand()");
        return 0;
    }
 
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }
 
    @Override
    public void onCreate(){
        super.onCreate();
        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onCreate()");
        if (mediaPlayer==null){
            mediaPlayer=MediaPlayer.create(this,R.raw.gumeng);
            mediaPlayer.setOnCompletionListener(this);
        }
        mediaPlayer.start();
    }
 
    @Override
    public void onCompletion(MediaPlayer mp) {
        stopSelf();
    }
 
    @Override
    public void onDestroy(){
        if(mediaPlayer.isPlaying()){
            mediaPlayer.stop();
        }
        mediaPlayer.release();
        stopForeground(true);
 
        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onDestroy()");
    }
 
    //为了和Activity交互,我们需要定义一个Binder对象
    class AudioBinder extends Binder {
 
        //返回Service对象
        AudioServiceOnBind getService(){
            return AudioServiceOnBind.this;
        }
    }
 
}

然后在调用的Activity中创建一个ServiceConnection对象重写其中的onServiceConnected方法获取所要绑定的服务。在触发事件的方法中调用bindService实现服务的最终绑定。

public class MainActivity extends AppCompatActivity {
 
    private AudioServiceOnBind audioServiceOnBind;
 
    //使用ServiceConnection来监听Service状态的变化
    private ServiceConnection conn = new ServiceConnection() {
 
        @Override
        public void onServiceDisconnected(ComponentName name) {
            audioServiceOnBind = null;
        }
 
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            //这里我们实例化audioService,通过binder来实现
            audioServiceOnBind = ((AudioServiceOnBind.AudioBinder) binder).getService();
        }
    };
 
  public void click_music_open(View view) {
 
        Intent intentService = new Intent(MainActivity.this, AudioServiceOnBind.class);
        bindService(intentService, conn, Context.BIND_AUTO_CREATE);
 
    }
}

生命周期:onCreate->onBind->onUnBind->onDestroy

  • onCreate() 当Service被创建时,由系统调用。

  • onBind() 当bindService方法启动Service时,该方法被调用。

  • onUnbind() 当unbindService方法解除绑定时,该方法被调用。

  • onDestroy() 当Service不再使用时,由系统调用。

  1. 实现前台Service
    Android 8.0 后系统不允许后台应用创建后台服务。 因此,Android 8.0 引入了一种全新的方法,即 Context.startForegroundService(),以在前台启动新服务。

在service onStartCommand方法中增加以下代码

 @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onStartCommand()");
        Intent nfIntent = new Intent(this, MainActivity.class);
 
        Notification.Builder builder = new Notification.Builder(this.getApplicationContext())
                .setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0))
                .setSmallIcon(R.mipmap.touxiang)
                .setContentTitle("wu")
                .setContentText("Android测试")
                .setWhen(System.currentTimeMillis());
 
        String CHANNEL_ONE_ID = "com.wu";
        String CHANNEL_ONE_NAME = "Channel One";
        //安卓8.1以上系统
        NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ONE_ID, CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_MIN);
        notificationChannel.enableLights(false);
        notificationChannel.setShowBadge(true);
        notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        manager.createNotificationChannel(notificationChannel);
        builder.setChannelId(CHANNEL_ONE_ID);
 
        Notification notification = builder.build();
        startForeground(1, notification);
        return super.onStartCommand(intent,flags,startId);
    }
        在调用Activity中调用startForegroundService方法。

 public void click_music_open(View view) {
 
        Intent intentService = new Intent(MainActivity.this, AudioServiceOnBind.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(intentService);
        } else {
            startService(intentService);
        }
    }
  1. 使用IntentService
    由于Service中的逻辑都是执行在主线程中的,此时如果在Service中处理一下耗时操作可能就会给用户带来不好的体验。所以此时就可以使用Android多线程Service.
    本质上IntentService是在Service里开启线程去做任务处理。IntentService会在任务执行完成后自行结束自己,而不需要外部去调用stopService了。

使用IntentService定义的服务,要开启线程,只要重写一个onHandleIntent()方法就可以了,而且在运行完之后会自动停止。

例如数据下载 数据上传等。

public class MyIntentService extends IntentService {
 
    private static final String TAG = "MyIntentService";
 
    public MyIntentService() {
        super("MyIntentService");
    }
 
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG, "当前是子线程: " + Thread.currentThread().getId());
        //在这里实现异步多线程处理逻辑
        //例如数据下载 数据上传等。
        Log.d(TAG, "我在后台默默下载数据中。。。。");
    }
 
    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate: ");
        super.onCreate();
    }
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand: ");
        return super.onStartCommand(intent, flags, startId);
    }
 
    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy: ");
        super.onDestroy();
    }
}

Broadcast Receiver

Content Provider

两大视图

  • project
  • android

在这里插入图片描述

主要结构目录

  • bulid
    编译时自生成文件
    在这里插入图片描述

  • libs
    第三方jar包,会被自动添加到构建路径中去
    在这里插入图片描述

  • java
    java代码

在这里插入图片描述

  • res
    项目中使用的所有资源,drawable存放图片,layout存放布局,values存放字符,mipmap存放图标
    在这里插入图片描述

  • Manifest
    AndroidManifest.xml配置文件,程序中定义的四大组件都需要在这个文件里注册,另外这个文件中还可以给应用程序添加权限声明
    在这里插入图片描述

  • bulid.gradle
    项目构建工具,通常有两个bulid.gradle,一个是项目级一个是app级

在这里插入图片描述

  • com.android.application
    应用程序模块

  • com.android.library
    库程序模块

区别:一个是可以直接运行的,一个只能作为代码库依附于别的应用程序模块来运行

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1984040.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

判断Windows设备是否为翻新

网购设备难免踩坑&#xff0c;一定要学会查验&#xff0c;及时保存证据并投诉商家。 1、查验包装信息&#xff0c;是否有拆封痕迹 商家翻新处理的第一道工序就是换个完整的包装&#xff0c;一般不会把拆过的包装打包卖给买家&#xff0c;除非声明是二手。 2、查验序列号&#x…

干货-并发编程提高——线程的唤醒(七)

没有参数的wait()方法等价于wait(0),等价于永远等下去。虚假唤醒&#xff1a;一个线程也能在没有被通知&#xff0c;中断&#xff0c;或超时的情况下被唤醒。也即所谓的“虚假唤醒”。解决虚假唤醒的办法就是通过while循环来判断条件。 何为虚假唤醒 简单讲&#xff0c;要避免使…

磷酸铁锂与三元锂:谁会取得压倒性的胜利?

在电动车市场中&#xff0c;磷酸铁锂&#xff08;LFP&#xff09;和三元锂&#xff08;NCM/NCA&#xff09;电池是两种主要的锂离子电池技术。近年来&#xff0c;关于这两种电池的讨论愈发热烈。本文将深入探讨磷酸铁锂与三元锂的真正区别&#xff0c;以及它们在未来电动车市场…

AI8-文本检测

文本检测任务是找出图像或视频中的文字位置。不同于目标检测任务,目标检测不仅要解决定位问题,还要 解决目标分类问题。 文本在图像中的表现形式可以视为一种‘目标‘,通用的目标检测的方法也适用于文本检测,从任务本身上来 看: • 目标检测:给定图像或者视频,找出目…

什么是SQL注入?基于实例讲解

一、SQL注入的含义&#xff1a; SQL注入是一种常见的网络攻击&#xff0c;由于程序对输入数据的判断或者检验不严格&#xff0c;导致攻击者查询到了授权范围之外的数据&#xff0c;甚至还可以修改数据库中的数据&#xff0c;对数据库执行一些管理操作等&#xff0c;所以它的危…

【Material-UI】Button 中的点击事件处理(Handling clicks)详解

文章目录 一、点击事件处理基础1. 基本用法2. 事件处理器的传递 二、实际应用中的注意事项1. 事件处理逻辑的优化2. 避免过多的状态更新3. 使用合适的事件类型 三、关于文档中未提及的原生属性四、最佳实践1. 无障碍性2. 视觉反馈3. 防止重复点击 五、总结 在现代前端开发中&am…

测试TLP 使用外部 50Ω 电缆和非 50Ω 电缆影响

测试目的 实验有 SMA 母头连接器与没有SMA母头连接器 I/V 曲线的影响实验 50Ω 电缆和非 50Ω 电缆应用条件下的 I/V 曲线研究初始启动和 16A DUT(被测器件)应用条件下的脉冲电压和脉冲电流影响 开始测试前先做短路/开路校正 短路校正 开路校正 TLP取样方式与为框黄色70ns~90…

详解线程池的使用

一、线程池基础 1.1、线程池的思想 我们首先理解什么是池化技术&#xff1a; 池化技术指的是提前准备一些资源&#xff0c;在需要时可以重复使用这些预先准备的资源。 池化技术的优点主要有两个&#xff1a;提前准备和重复利用。 下面是池化技术常见的应用场景&#xff1a; …

SpringBoot+Redis 发布与订阅

两个应用都引入 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artif…

机器学习入门之无监督学习(聚类、降维(主成分分析)、关联度分析(Apriori 算法))

无监督学习是机器学习的一种类型&#xff0c;它处理没有显式标签的数据。与监督学习不同&#xff0c;无监督学习的目标是探索数据的内在结构和模式&#xff0c;而不是从标注数据中学习一个特定的映射到预定标签的函数。这使得无监督学习特别适用于探索性数据分析、找寻隐藏模式…

关于加载水印PDF、图片以及压缩包格式文件【把博客当工作记录】

写这篇文章的目的是让大家都可以学到东西,核心代码中列出了处理思维和调用方法,业务代码已经过滤掉了,希望大家不要做crud程序员!!要思考。。。该博客不懂时可联系下方。 1、流程图如下 2、策略描述 实现方式: 设计模式:父策略调动子策略 业务理念:在不影响原有业务…

【电脑基础硬件】从零开始认识主板

从零开始认识主板 一、主板及其元器件二、主板上的各个部件通信三、主板的选择 注意&#xff1a; 以下以Z790电脑主板为例进行说明。 一、主板及其元器件 IO接口&#xff1a; CPU模块 CPU是电脑的大脑&#xff0c;控制并指挥着电脑的各个模块协同工作。CPU通过主板上的插槽固定…

电路中电阻,电容和电感作用总结

电阻作用 1&#xff0c;上拉电阻 电阻的连接一般是一端接上拉的电源&#xff08;一般与芯片信号的电压值相匹配&#xff09;&#xff0c;另一端连接芯片引脚所对应的信号大概如下图 功能&#xff1a;一、预置某些引脚的功能&#xff0c;例如复位信号拉高&#xff08;失能&…

疯传!平台培养“斗士”的背后,是 AI 智能名片与 O2O 商城小程序在搞鬼

摘要&#xff1a;本文探讨了在搭建用户聚集平台以筛选和培养“斗士”的过程中&#xff0c;如何融入 AI 智能名片和 O2O 商城小程序。详细阐述了贴吧或论坛作为初始平台的优势&#xff0c;以及如何通过适当的管理和引导活动筛选出“储备斗士”。同时&#xff0c;分析了 AI 智能名…

浅谈 Mybatis 框架

文章目录 一、什么是MyBatis?1.2、JDBC 二、使用Mybatis2.1、配置MyBatis开发环境2.1.1、配置连接字符串2.1.2、配置MyBatis中的XML路径 2.2、使用MyBatis模式和语法操作数据库 三、使用 Mybatis 进行增删改查操作的要点3.1、ResultMap的用法 四、Mybatis操作难点4.1、#{ } 和…

Modbus-TCP详解

目录 Modbus-TCP Modbus TCP协议的帧结构如下&#xff1a; 实现Modbus-Tcp 使用EasyModbusTCP第三方实现Modbus-Tcp EasyModbusTCP的使用 设置IP 设置端口 设置设备地址 开启通讯 读取寄存器 写入寄存器 实例 Modbus-TCP Modbus TCP是Modbus协议的一种变体&#xff0c;它使用T…

Java多线程的单例设计模式 多种实现方法

目录 前言 饿汉式 懒汉式 Double_check volatile double_check Holder方式 枚举 前言 单例设计模式GOF23中设计模式中最常用的设计模式之一, 单例设计模式提供了多线程环境下的保证唯一实例性的解决方案, 虽然简单, 但是实现单例模式的方式多种多样, 因此需要从多个维度去…

【云原生】恰当运用kubernetes中三种探针,确保应用程序在Kubernetes集群中保持健康、可用和可靠

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Unity热更——ILRuntime安装接入

一、ILRuntime相关地址 1、官网文档地址 2、GitHub上开源的ILRuntime项目工程 3、GitHub上的官方ILRuntime-Unity实例工程 4、官方视频教程-Unity中文课堂&#xff08;需付费&#xff09; 5、ILRuntime入门笔记-赵青青-博客园 6、ILRuntime 的学习-简书 二、ILRuntime…

Python | Leetcode Python题解之第324题摆动排序II

题目&#xff1a; 题解&#xff1a; def quickSelect(a: List[int], k: int) -> int:seed(datetime.datetime.now())shuffle(a)l, r 0, len(a) - 1while l < r:pivot a[l]i, j l, r 1while True:i 1while i < r and a[i] < pivot:i 1j - 1while j > l an…