ANR
ANR全称Application Not Responding
,意思就是程序未响应。
出现场景
- 主线程被IO操作(从4.0之后网络IO不允许在主线程中)阻塞。
- 主线程中存在耗时的计算
- 主线程中错误的操作,比如Thread.wait或者Thread.sleep等
Android系统会监控程序的响应状况,一旦出现下面两种情况,则弹出ANR对话框
- 应用在5秒内未响应用户的输入事件(如按键或者触摸)
- BroadcastReceiver未在10秒内完成相关的处理
好好努力,天天向上
广播(Broadcast)机制用于进程/线程间通信,广播分为广播发送和广播接收两个过程,其中广播接收者BroadcastReceiver便是Android四大组件之一。
BroadcastReceiver分为两类:
静态广播接收者
:通过AndroidManifest.xml
的标签来申明的BroadcastReceiver。动态广播接收者
:通过AMS.registerReceiver()
方式注册的BroadcastReceiver,动态注册更为灵活,可在不需要时通过unregisterReceiver()
取消注册。
标准模式。每次启动Activity都会创建新的实例。谁启动了这个Activity,那么这个Activity就运行在谁的Task中。不能使用非Activity类型的context
启动这种模式的Activity,因为这种context
并没有Task,这个时候就可以加一个FLAG_ACTIVITY_NEW_TASK
标记位,这个时候启动Activity实际上是以singleTask模式启动。
Android 系统将尽量长时间地保持应用进程,但为了新建进程或运行更重要的进程,最终需要清除旧进程来回收内存。 为了确定保留或终止哪些进程,系统会根据进程中正在运行的组件以及这些组件的状态,将每个进程放入“重要性层次结构”中。 必要时,系统会首先消除重要性最低的进程,然后是重要性略逊的进程,依此类推,以回收系统资源。
重要性层次结构一共有 5 级。以下列表按照重要程度列出了各类进程(第一个进程最重要,将是最后一个被终止的进程):
前台进程:用户当前操作所必需的进程。如果一个进程满足以下任一条件,即视为前台进程:
托管用户正在交互的 Activity(已调用 Activity 的 onResume()
方法)
托管某个 Service,后者绑定到用户正在交互的 Activity
托管正在“前台”运行的 Service(服务已调用 startForeground()
)
托管正执行一个生命周期回调的 Service(onCreate()
、onStart()
或 onDestroy()
)
托管正执行其 onReceive()
方法的 BroadcastReceiver
通常,在任意给定时间前台进程都为数不多。只有在内在不足以支持它们同时继续运行这一万不得已的情况下,系统才会终止它们。 此时,设备往往已达到内存分页状态,因此需要终止一些前台进程来确保用户界面正常响应。
在上面的图中存在不同状态之间的过渡,但是,这些状态中只有三种可以是静态,也就是说 Activity 只能在三种状态之一下存在很长时间。
继续:在这种状态下,Activity处于前台,且用户可以与其交互(又称为运行态,在调用 onResume()
方法调用后)。
暂停:在这种状态下,Activity被在前台中处于半透明状态或者未覆盖整个屏幕的另一个Activity—部分阻挡。 暂停的Activity不会接收用户输入并且无法执行任何代码。
停止:在这种状态下,Activity被完全隐藏并且对用户不可见;它被视为处于后台。 停止时,Activity实例及其诸如成员变量等所有状态信息将保留,但它无法执行任何代码。
其他状态(“创建”和“开始”)是瞬态,系统会通过调用下一个生命周期回调方法从这些状态快速移到下一个状态。 也就是说,在系统调用 onCreate()
之后,它会快速调用 onStart()
,紧接着快速调用 onResume()
。
compileSdkVersion
告诉 Gradle 用哪个 Android SDK 版本编译你的应用。使用任何新添加的 API 就需要使用对应 Level 的 Android SDK。
需要强调的是修改 compileSdkVersion
不会改变运行时的行为。当你修改了 compileSdkVersion
的时候,可能会出现新的编译警告、编译错误,但新的 compileSdkVersion
不会被包含到 APK 中:它纯粹只是在编译的时候使用。(你真的应该修复这些警告,他们的出现一定是有原因的)
因此我们强烈推荐总是使用最新的 SDK 进行编译。在现有代码上使用新的编译检查可以获得很多好处,避免新弃用的 API ,并且为使用新的 API 做好准备。
注意,如果使用 Support Library
,那么使用最新发布的 Support Library
就需要使用最新的 SDK 编译。例如,要使用 23.1.1 版本的 Support Library
,compileSdkVersion
就必需至少是 23 (大版本号要一致!)。通常,新版的 Support Library
随着新的系统版本而发布,它为系统新增加的 API 和新特性提供兼容性支持。
1) 继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继 承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的 重要手段。
2) 封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象 的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我 们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程 接口。
3) 多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调 用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外 界提供的服务,那么运行时的多态性可以解释为:当 A 系统访问 B 系统提供的服务时,B 系统有多种提供服务的方式, 但一切对 A 系统来说都是透明的。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写 (override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做 两件事:1. 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2. 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。
4) 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对 象有哪些属性和行为,并不关注这些行为的细节是什么。
在上一篇文章讲述zuul的时候,已经提到过,使用配置服务来保存各个服务的配置文件。它就是Spring Cloud Config。
在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件spring cloud config ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在spring cloud config 组件中,分两个角色,一是config server,二是config client。