博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android入门第一关:Android四大组件
阅读量:6914 次
发布时间:2019-06-27

本文共 5220 字,大约阅读时间需要 17 分钟。

前言

我们是程序员,每天都在了解最新的技术,每天都在学习编程语言、框架或者库。很多人都有这样的感觉,不要再更新了,我已经学不动了。

要知道新的东西每年都在变化,可能之前很火的框架现在已经不再用了。对于程序员来说,打好基础才是主要的。

今天把Android的四大组件总结一下,这块也是面试中的高频问题区域。

Activity

生命周期

对于Activity,来说最主要的就是它的生命周期了。

Activity从开始创建到结束的生命周期依次是
onCreate()->
onStart()->
onResume()->
onPause()->
onStop()->
onDestroy()

方法 调用时机
onCreate() 首次创建Activity时调用,可以进行创建视图,绑定数据等。
onStart() 在Activity即将对用户可见之前调用
onResume() 开始和用户进行交互之前调用
onPause() 开启另一个Activity或者锁屏时调用
onStop() 当前Activity对用户不可见时调用
onDestory() 在Activity被销毁时调用
onRestart() 在Activity已经停止即将再次启动时调用

四种状态

  1. 活动状态(running): Activity处于可见状态,在屏幕前台,即在栈顶。 期间的生命周期为onCreate->onStart->onResume
  2. 暂停状态(paused): 已经失去焦点但是仍可见的状态(包括部分可见)。触发的生命周期:onResume-> onPause
  3. 停止状态(stoped): 该Activity被另一个Activity完全覆盖的状态,onPause -> onStop
  4. 死亡状态(destroyed): 该Activity完全被销毁,onStop -> onDestroy
切换屏幕时生命周期变化

分为三种情况:

  1. 没有设置AndroidManifest中的configeChanges。 不论是横屏切竖屏还是竖屏切横屏都是这样的: onPause()-> onSaveInstanceState()->onStop()->onDestroy()->onCreate()->onStart()->onRestoreInstanceState()->onResume()->onPause()->onStop()->onDestroy()

  2. 设置configeChangsorientation6.0同1一样,7.0先走onConfigurationChanged方法,然后和1一样,8.0只会走onConfigurationChanged方法

  3. 设置configeChangsorientation|keyboardHidden|screenSize或者onfigurationChanged`方法

启动模式

启动模式 说明
standrad 默认模式,每次创建都会新建新的实例
singleTop 如果该Activity在栈顶,将不会新建,会回调onNewIntent方法,没有在栈顶,将会新建。适合于通知启动的页面
singleTask 栈内复用,如果栈中存在该Activity的实例,则会将该Activity置顶,将上面的Activity全部出栈,回调onNewIntent,否则创建新的实例,压入栈。像一些程序的入口,只能有一个实例,这个任务栈是通过taskAffinity属性指定的。
singleInstance activity只能单独在一个任务栈中,单例模式。像系统Launcher、锁屏键、来电显示等系统应用都是使用这种模式

可以通过adb shell dumpsys activity activities来查看现有的Activity。

注:启动模式,是每次面试必问的内容,划重点。

Service

什么是Service

Service可以说是一个在后台运行的Activity,它不是一个单独的进程,也不是一个单独的线程,它只需要应用告诉它应该做什么就可以了。

它用于处理一些不干扰用户使用的后台操作。比如播放多媒体、检测SD卡上文件的变化等。

注:默认情况下,Service所有的代码都是运行在主线程上,不能进行比较耗时的操作,可以在Service中创建Thread来执行耗时的操作。

为什么不适用后台线程而使用Service?

  1. Service可以放在独立的进程中,所有更安全。
  2. 使用Service可以依赖现有的binder机制,不需要在应用层上处理线程同步的繁杂工作。
  3. 系统可以重新启动异常死去的Service

分类

本地服务

本地服务,也叫做进程内服务,是应用于程序内部的。执行一些耗时的操作。 本地服务根据启动方式的不同分为:被启动服务Started Service和被绑定服务Bound Service

服务 说明
Started Service 由其他组件调用startService方法调用,该方法会导致被启动的服务的onStartCommand被回调。当服务被启动之后,就与启动者的生命周期没有关联,即使启动者被销毁,改服务也会继续执行,除非调用stopSelf()或者stopService()来停止
Bound Service Activity通过bindService方法来绑定服务,同时该Activity要提供ServiceConnection接口的实现类,用来监视Activity与服务类之间的连接,Service必要实现onBind()方法,返回Ibinder对象(定义服务类与Activity交互的程序接口),重写onServiceConnected() 方法,将服务赋值到Activity中

onStartCommand()方法有三种返回值:

  • START_STICKY: (粘性)使用这个返回值时,我们启动的服务根应用程序"粘"在一起,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,当再次启动服务时,传入的第一个参数将为null。
  • START_NOT_STICKY:(非粘性)相对应的,被kill掉之后不会重新启动该服务。
  • START_REDELIVER_INTENT:使用这个返回值之后,被系统kill掉之后,不但会重新启动该服务,还会将intent的值传入。
远程服务

绑定远程服务的步骤:

  1. 在服务的内部创建一个内部类,提供一个方法,用于间接调用服务里的方法。
  2. 把暴露的接口文件的扩展名改为.aidl文件,去掉访问修饰符。
  3. 实现服务的onBind 方法,实现aidl定义的接口,提供给外界可调用的方法。
  4. 在Activity中绑定服务。
  5. 提供ServiceConnection方法的实现类,重写onServiceConneced方法,传递IBinder对象。
  6. aidl定义的接口Stub.asInterface(binder)调用接口里的方法。

生命周期

  1. Start Service生命周期:
  • 在程序中调用startService(),如果该Service还没有运行,就会执行onCreat()onStartCommand()回调方法,如果已经运行了就会执行onStartCommand()方法。
  • 调用context.stopService()会执行该服务的onDestroy方法,如果没有调用该方法,此服务将会一直在后台运行。
  1. Bound Service 生命周期:
  • 在程序中调用context.bindService会触发执行该服务的onCreate()onBind()方法。onBind方法会返回一个iBinder的接口实例,用来回调服务里的方法。
  • 如果调用者Context退出了,那么会依次执行onUnbind()onDestroy()方法。

IntentService

IntentService是Service的子类,主要用于处理异步请求,防止线程的阻塞。所有的请求将在一个工作线程(HanderThread)中处理,工作完成了,线程也就结束了。

IntentService中提供了一个onBind()方法的默认实现,返回null。提供一个onStartCommand()方法的默认实现,它将intent想传送到工作队列,然后从工作队列中每次取出一个传送至onHandelIntent()方法,在该方法中对intent做相应处理。

BroadcastReceiver

广播是一个全局的监听器,分为广播发送者和广播接受者。

原理浅析

广播采用的是观察者模式,和eventbus一样基于消息的发布/订阅事件模型,通过AMS(Activity Manager Service)来处理消息中心来协调处理广播发送者和广播接受者。

  1. 广播接受者通过Binder机制在消息中心注册。
  2. 广播发送者通过Binder机制发送广播。
  3. AMS消息中心通过发送者的要求,在消息列表中找到符合条件的接受者。
  4. AMS将广播发送到符合条件的接受者的消息队列中。
  5. 接受者通过消息循环拿到消息,回调onRevice,进行相应处理。

使用

  • 继承BroadcastReceivre类。
  • 重写onReceive方法,在接受广播时做相应处理。

注:如果有耗时的操作,不要直接在onReceive中执行,默认情况下,接受器是运行在 UI中的,建议在Service中开启线程执行。

根据注册方式的不同,注册分为静态注册和动态注册。

静态注册

AndroidManifest声明:

复制代码
动态注册
registerReceiver(new MyBroadcastReceiver(),new IntentFilter("chang"));复制代码

要加上权限

复制代码

两者的区别

注册方式 区别
静态注册 常驻广播,需要时刻关注广播
动态注册 非常驻,跟随组件生命周期变化,注意要在组件销毁前取消注册

类型

广播的类型可以分为五类

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

普通广播也就是我们开发者自定义的intent广播。

sendBroadcast(intent)复制代码

当接受者的action与发送的intent中的action一致时,就会回调onReceive方法。

系统广播就是一些手机上基本操作的变更发出的广播,比如网络状态变化、电池电量等。

有序广播就是发送出去的广播接受者按照顺序接受,现接受到的可以拦截或者修改该广播。

sendOrderedBroadcast(intent);复制代码

应用内广播是一种局部广播,发送者和接受者都在app内,并不对外暴露。 一种实现方式是将exported设置成false,指定包名发送广播。 另一种是使用LocalBroadcastManager动态注册广播

ContentProvider

ContentProvider:内容提供者,有时候我们需要吧我们自己的数据暴露给其他程序使用,这时候就需要ContentProvider来实现,其他程序通过 ContentResolver来操作暴露的数据。

当应用通过ContentProvider来暴露自己的数据之后,不管该应用是否启动,都可以通过该接口来操作其内部数据,像一些增删改查操作。

开发一个ContentProvider的步骤如下:

  1. 自定义个一个ContentProvider类,继承ContentProvider基类。
  2. AndroidManifest.xml文件中注册这个ContentProvider,绑定一个Uri。
  3. 实现其基类的几个方法,做相应处理。
  • onCreate():第一次访问时,会回调该方法。
  • insert
  • delete
  • update
  • query
  • getType: 返回当前Uri所代表的数据的MIME类。

insert、delete、update、query,对当前Uri进行增删改查操作。

其他程序通过创建ContentResolver来操作ContentProvider暴露的数据。一般来说ContentProvider是单例模式的,ContentResolver操作数据,其实是委托给Uri对应的ContentProvider来进行处理。

总结

看完之后,是否对Android的四大组件:Activity、Service、BroadcastReceiver、ContentProvider有了深刻一点的印象。这里我没有列出一些具体的实现各个组件的例子,我相信看完之后,自己就能很好地写出来。

多积累、多总结、多思考,每天比昨天多努力一点点。

转载地址:http://viacl.baihongyu.com/

你可能感兴趣的文章
CentOS中service命令与/etc/init.d的关系以及centos7的变化
查看>>
scapy网络嗅探
查看>>
内网esxi主机上安装CoreOS虚拟机
查看>>
数组算法(一)
查看>>
java中读取txt文件获得编码格式方法
查看>>
Python数据结构__树
查看>>
hql的一些坑org.hibernate.hql.internal.ast.QuerySyntaxException
查看>>
Velocity 模板如何显示 $! , ${} 等特殊符号
查看>>
从定性遥感到定量遥感——大数据时代的空间数据科学
查看>>
一行代码更新R语言
查看>>
在hibernate中查询使用list,map定制返回类型
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
String字符串
查看>>
SolarWinds-DesktopToolset
查看>>
我的友情链接
查看>>
Mac sudo 命令不能用报错处理
查看>>
RHEL7上配置NFS服务
查看>>
我的友情链接
查看>>
Vim编辑器
查看>>