Android笔试准备
文章目录
序章、Android相关
0.1、Android系统架构
-
应用程序层
java语言应用程序开发
-
应用程序框架层
java语言OS定制。framework层开发
-
系统运行库层
C C++实现so库
-
Linux内核
0.2、 Android 的四大组件
Activity、Service、BroadcastReceiver、ContentProvider
活动、服务、广播接受者、内容提供者
-
Activity
一个活动通常展现为一个可视化的界面,是Android程序与用户交互的窗口,也是Android最基本也是最复杂的组件。
从视觉效果上看
占据当前窗口、响应所有窗口事件
从内部逻辑上看
Activity需要保持各个界面的状态,需要很多持久化的事情,还需要妥善管理生命周期和一些跳转逻辑操作
-
Service
服务是运行在后台的一个组件,像是一个没有界面的Activity
封装有一个完整的逻辑功能的实现,接收上层指令,完成相关的事件
定义好需要接受的Intent提供同步和异步的接口
-
BroadcastReceiver
广播是在应用之间传输信息的机制
广播接收者是对发送出来的广播进行过滤接受并响应的一类组件
不包含任何用户界面,可以启动一个Activity或Service响应接收到的信息
Android中还有一个重要的概念
-
Intent
是一个动作或行为的抽象描述,负责组件之间,进程之间进行消息传递
Broadcast组件就提供了一个把Intent作为消息广播出去,由所有对其感兴趣的程序对其作出反应的机制
-
-
Content Provider
内容提供者,作为应用程序之间唯一的共享数据的途径
多应用之间的数据共享
储存并检索数据以及向其他应用程序提供访问数据
第一章、Activity
1.1、Activity的生命周期
创建完成Activity之后需要用setContentView来完成界面的显示
设置内容界面SetContentView
-
Activity之间通过Intent进行通信
-
Android中会维持一个Activity栈,Stack
-
当一个新的Activity创建时,他会被放到栈顶,这个Activity就处于运行状态
-
另一个新的Activity被创建时,会被重新压入栈顶,之前的Activity则会被压在底下进入后台
-
有四种状态
- 运行中(Running、active)可见,可交互
- 暂停(paused)当Activity失去焦点,不能跟用户交互,但依然可见,非全屏的Activity或者透明的Activity在栈顶
- 停止(Stoped) 被另一个Activity完全覆盖,或者点击Home进去后台,Activity处于停止状态,数据还被保持着
- 销毁(destroyed)当我们按返回键或者内存不够的情况下,就会把Activity从栈里移除销毁,被系统回收
1.2、Activity 的四种启动模式
-
standard
标准模式,调用startActivity就会产生一个新的实例
-
singleTop
如果已经有一个实例位于Activity栈的顶部时,就不产生新的实例,只是调用newInstance方法
如果不位于栈顶,会产生一个新的实例
-
singleTask
会在一个新Task中产生这个实例,以后每次调用都会使用这个,不去产生新的实例
-
singleInstance
基本跟singleTask一样
区别
- 这个模式下的Activity实例所处的Task中,只能有这个Activity实例,不能有其他实例
1.3、Activity的onSaveInstanceState()和onRestoreInstanceState()
Activity的onSaveInstanceState()和onRestoreInstanceState()并不是生命周期方法,不同于onCreate、onPause等方法,并不一定会被触发,
当应用遇到意外情况:内存不足、用户直接按Home键,
由系统销毁一个Activity时,onSaveInstanceState会调用,
但是当用户主动去销毁一个Activity时,例如按返回键,onSaveInstanceState方法就不会被调用,通常onSaveInstanceState只适用于保存一些临时状态,而onPause适用于数据的持久化保存。
另外,当屏幕的方向发生改变,Activity会被摧毁并且被重新创建,如果想在Activity被摧毁之前缓存一些数据、并且在Activity被重新创建之后恢复缓存的数据,可以重写Activity的onSaveInstanceState方法和onRestoreInstanceState方法
1.4、横竖屏切换的生命周期
- 不设置android:configChanges时,切屏会重新调用各个生命周期,且横屏一次,切竖屏两次
- 设置android:configChanges=“orientation”,重新调用,一次
- 设置android:configChanges=“orientation|keybordHidden”,切屏不会重新调用生命周期,只会至此那个OnConfigurationChanged方法
1.5、如何退出Activity,如何安全退出
finish即可退出
KillProcess()或者System.exit()
定义一个Activity基类,处理这些共通问题
- 每打开一个Activity就记录,需要退出时,关闭每一个Activity即可
- 需要结束应用时,发送一个特定广播
第二章 Service
2.1 Service的两种分类
-
本地服务LocalService
本地服务依附在主进程上,而不是独立的进程
一定程度上节约了资源,另外Local服务器因为是同一进程因此不粗要IPC,也不需要AIDL
- 相应bindService会方便很多,主进程被Kill后,服务便会终止
-
远程服务RemoteService
远程服务为独立的进程,对应进程名格式为所在包名加上你指定的Android:process字符串,由于是独立的进程,因此所在进程被Kill之后,该服务依然在运行
不受其他进程影响,独立的进程会占用一定资源,进行IPC稍微麻烦一点
按使用方式可以分为以下三种
- startService启动的服务:启动 一个服务执行后台任务,不进行通信
- bindService启动的服务:启动的服务,可以进行通信
- startService并bindService
2.2 Service 与 Thread 的区别
-
Thread
程序执行的最小单元,分配CPU的基本单位,可以用Thread执行一些异步操作
-
Service
是安卓的一种机制,组件。
-
如果是LocalService,对应的Service是运行在主进程的main线程上的,onCreate、onStart都是运行于此
-
如果是RemoteService,运行在独立进行的main线程上
-
-
为什么用Service
Thread运行独立于Activity,Activity被finish之后,新的Activity无法控制Thread,会在后台一直运行
因而需要创建一个Service,在Service里面创建、运行并且控制Thread,这便解决了这个问题(因为Activity都可以控制同一个Service,而系统也只会创建一个对应的Service实例)
2.3、Service和Activity通信
需要用到bindService,通过onBind()方法实现
2.4、Service的启动模式
-
用start的方式开启服务
startService(Intent)启动服务
stopService(Intent)停止服务
-
生命周期
onCreate()-onStartCommond()-onDestory()
-
服务停止的时候调用onDestory()服务只会被停止一次
-
服务一旦开启和开启者没有关系
-
开启者退出,服务还在后台长期运行
-
开启者不能调用服务里面的方法
-
-
使用bind的方式开启服务
bindService(Intent,ServiceConnection,int)绑定
unbindService(ServiceConnection)停止服务
-
生命周期
onCreate()-onBind()-onunbind()-onDestory()
-
绑定服务,调用者挂了,服务也会跟着挂
-
绑定者可以调用服务里面的方法
-
第三章、BroadcastReceiver
3.1、注册广播的方式
-
动态注册
代码动态注册,优先级高于静态注册,因此在必要的情况下使用动态注册
- 非常驻型常驻型广播,广播跟随Activity的生命周期
- 常驻型,当有应用程序关闭后,广播功能开启
-
静态注册
动态注册的特点:用来注册的Activity被销毁之后,广播失效
静态注册,只要设备是开启状态,广播接收器开着,在清单文件中通过注册
第四章、ContentProvider
第五章、Intent
5.1、Intent的作用
动作或行为的抽象描述,负责组件或者进程之间的消息传递
负责对应用中的一次操作的动作、动作涉及数据、附加数据进行描述
Android会找到对应的组件,完成组件的调用
有两种方式
-
显式匹配
明确指定要跳转的Activity或者Service,明确指定了组件名
-
隐式匹配
没有明确指定组件名,Android会根据隐式意图中设置的动作(action)类别(category)、数据(URI和数据类型)找到合适的组件来处理这个意图
5.2、Intent传递数据大小
Intent传递大数据,会出现TransactionTooLargeException
因为使用了Binder通信机制
Intent中的数据,会被作为Parcel被存储在Binder的事务缓冲区中的对象进行传输。 、
这个Binder事务缓冲区有一个有限的固定的大小,目前是1MB
第六章、Handler
6.1、Handler机制
进程之间的消息传递机制
我们常常将一些耗时的操作放在子线程里面了,然后将执行的结果告诉UI线程
用法,创建一个Handler,重写handleMessage方法
线程中,通过创建的Handler的obtainMessage方法或者一个Massage实例
然后通过sendMessage方法发送出去
Android提供了Handler和Looper来满足线程间的通信,
Handler先进先出原则
Looper类用来管理特定线程内对象之前的信息交换(MessageExchange)
-
Looper:一个线程可以产生一个Looper对象,由他管理此线程里的消息队列(MessageQueue)
-
Handler:可以构造Handler对象来和Looper进行沟通,以便push新消息到MessageQueue里,或者接收Looper从MQ里取出的消息
-
MessageQueue
用来存放线程放入的消息
-
线程
UI Thread通常就是main Thread,而Android启动程序时会替他建立一个MQ
6.2、在单线程模型中Message、Handler、Message Queue、Looper之间的关系
-
Handler获取当前线程中的Looper对象,Looper用来从存放Message的MQ中取出Message,再由Handler进行Message的分发和处理
-
MQ(消息队列)
用来存放通过Handler发布的消息,通常附属某一个创建它的线程,可以通过Looper.myQueue得到当前线程的消息队列
-
Handler
可以发布或者处理一个消息或者操作一个 Runnable,通过 Handler发布消息, 消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息
-
Looper:
是 Handler 和消息队列之间通讯桥梁,程序组件首先通过 Handler 把消息传递给 Looper,Looper 把消息放入队列。Looper 也把消息队列里的消息广播给所有的
-
Handler:
Handler 接受到消息后调用 handleMessage进行处理
-
Message:
消息的类型,在 Handler 类中的 handleMessage 方法中得到单个的消息进行处理
6.3、概念介绍
-
Message
线程之间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程
6.4、IPC、AIDL
IPC(Inter-ProcessCommunication)进程间通信
AIDL(Android Interface Dedinition Language)
Android 内部进程通信 接口 描述 语言
通过他我们可以定义进程间的通信接口,
编译器可以通过拓展名为aidl的文件生成一段代码,通过预先定义的接口达到进程内部通信的目的
Broadcast可以实现进程间通信
ContentProvider提供进程间数据共享
第七章 其他相关
7.1、AndroidMainfest.xml文件中包含哪些信息
说明应用程序的java包,该包名是应用程序的唯一标识
申明应用程序的权限,
Android API最低版本
有哪些组件组成
7.2、Android数据存储方式
-
SharedPreference方式
是Android提供的用来储存一些简单配置信息的一种机制。
采用了XML格式(键值对)将数据存储到设备中,只能在同一个包内使用
-
文件存储方式
SD卡存储多媒体文件
-
Sqlite方式
Android自带的标准数据库,轻量级的嵌入式数据库
-
内容提供器
主要用于程序之间的数据交换,从而能够让其他应用保存或读取此数据格式
-
网络存储
xml,json格式,通过httpURIConnection,SOAP协议获取数据
7.3、Android常用的几种布局
-
FrameLayout 帧布局
从屏幕的左上角开始布局,叠加显示
-
LinearLayout 线性布局
垂直水平布局
-
AbsoluteLayout 绝对布局
用X,Y来定位的布局方式
-
RelativeLayout
相对布局,以某一个元素为参照物
-
TableLayout
表格行 TableRow
7.4、通信方式
-
线程之间
- Handler
- Broadcast
- SharedPreference
-
进程间的通信方式
- Intent
- ContentProvider
- BroadCast
7.5、Android的动画类型
-
Tween动画 补间动画
View Animation 视图动画
视图组件移动、放大、缩小、透明变化
-
Frame动画 帧动画
Drawable Animation
传统的动画,通过顺序播放排列好的图片来实现,类似电影
-
Property Animation 属性动画
Android 3.0之后加入
7.6、如何实现屏幕分辨率的自适应
最好可以通过权重(layout_weight)的方式来分配每个组件的大小
尽量使用RelativeLayout
在Mainfest中配置后,添加不同分辨率的图片资源
7.7、Android程序的入口
在AndroidMainfest.xml文件中配置、
android.intent,action,MAIN表明他所在的Activity是整个应用程序的入口
7.8、Android哪几种方式访问网络
- HttpURLConnection
- HttpClient
7.9、Android MVC
Model、View、Control
-
Model模型
应用程序的主体部分,所有业务逻辑都写在该层
体现在Activity上,通过Activity交割model业务逻辑层处理
-
View视图
是应用程序中负责生成界面的部分,也是在整个MVC框架中可以被看到的一层,接收用户的输入,显示处理的结果
采用XML文件进行界面的描述,也可以使用html+javascript等方式作为安卓的view层。
-
Control控制
根据用户的输入,控制用户界面数据显示以及更新Model对象状态的一部分,控制器
对数据库,对网络的操作都放在model里面,对业务计算等操作也应该放在该层
7.10、安卓的数字签名
- 所有的应用都应该有数字证书,Android系统不会安装一个没有数字证书的应用程序
- Android程序包使用的数字签名是可以自签的,
- 正式发布的Android应用,必须使用一个合适的私钥生成的数字证书来给程序签名
- 数字证书有有效期,Android只是在应用安装的时候才会检查证书的有效期,如果应用已经安装在系统中,及时证书过期也不影响程序的正常使用。
7.11、Android SDK
NDK是一系列工具的集合。帮助开发者快速开发C或C++的动态库,并能自动将so和java应用一起打包成apk。极大的减轻了开发人员的打包工作。
7.12、为什么Intent和Bundle中携带的对象需要支持序列化
因为Intent中支持传递基本类型的数据,以及String和数组集合
如果你想传递一个自己的对象,那必须要序列化才行。
序列化相当于把这个对象转化成了字符串,然后传递过去,再反转化为对象
第八章、异常
8.1、什么是ANR,如何避免
ApplicationNotResponding
在Android中,活动管理器和窗口管理器这两个系统管理器负责监视应用程序的响应,当出现以下情况会出现ANR
- 用户对应用程序的操作5秒内无反应
- Broadcast10秒内仍然未执行完毕
Android的应用程序完全运行在一个独立的线程中,这就意味着任何在主线程中运行的需要消耗大量时间的操作都会引发ANR,因为此时,你的应用程序已经没有机会去响应输入事件和意向广播。
避免方法:
Activity应该在它的关键生命周期方法,比如onCreate和onResume里尽可能减少创建操作,潜在的耗时操作,网络或者数据库操作,高耗时的计算应该在子线程或者异步完成。
主线程应该为子线程提供一个Handler,一边完成时能够交给主线程
8.2、 OOM
OutOfMemoryException
内存泄露导致内存溢出,又称为OOM
-
什么情况下出现
- Bitmap占用内存太大
- 查询数据库没有关闭游标
- 不用的对象没有及时释放对象的引用
- 构造Adapter时,没有使用缓存的convertView
-
Android内存优化策略:
- 不用的Bitmap及时用recycle释放
- 过大图片分段加载
- 数据库的游标及时关闭
- 不用的对象及时释放,即指向NULL
- 在循环内尽量不要使用局部变量
- 尽量避免Static成员变量引用资源耗费过多的实例
Android给图片分配的内存只有8M。