1.handler机制
当我们需要在子线程处理耗时的操作(例如访问网络,数据库的操作),而当耗时的操作完成后,需要更新UI,这就需要使用Handler来处理,因为子线程不能做更新UI的操作。Handler能帮我们很容易的把任务(在子线程处理)切换回它所在的线程。简单理解,Handler就是解决线程和线程之间的通信的。
Handler发送Message到MessageQueue中
Looper从MessageQueue取出Message
Message扔给Handler由对应的处理者处理
2.Android四大组件(重点看下广播和服务)
①activity 提供用户界面 用于与用户交互的组件,(活动窗体)它需要为保持各界面的状态,做很多持久化的事情,妥善管理生命周期以及一些跳转逻辑
②content Provider
为应用程序之间访问提供的接口的组件,实现数据共享,结构化数据集合,以表的形式对外提供数据,可以像数据库一样记性选择排序
③BroadCastReceiver (广播)
采用异步机制完成组件之间消息的传递,异步是指广播的发送方将消息标记后发出,不需要得到对方的回应,可以继续做自己的操作
默认情况下,所有的组件都有接收广播的能力,组件想要接收广播就注册与发送方一致的标记
包括普通广播和有序广播:
发送有序广播:sendOrderedBroadCast(…);
有序广播可以进行应用程序之间传递消息,可以根据manifest文件中注册的优先级的高低判断接收的顺序。
无序广播:sendBroadCast();
实现过程:
创建一个类继承BroadCastReceiver,重写其中的onReceiver()方法,进行接收广播之后的操作。
广播 的生命周期注册方式:
- 程序代码中动态注册 退出时要取消注册。特点:关掉后,广播就失效了
- 清单文件中静态注册。 特点:无需关心广播接收器是否关闭,广播触发时,即使退出应用也会对它起作用
④server(服务)
不需要提供用户界面,在后台运行服务于activity,执行长时间耗时操作的组件
3.数据存储方式
- 文件存储数据
通过读取文件里的文件io流,SD卡等存储
核心原理: Context提供了两个方法来打开数据文件里的文件IO流 ,FileInputStream openFileInput(String name); FileOutputStream(String name , int mode),
这两个方法第一个参数 用于指定文件名,第二个参数指定打开文件的模式。 - 网络存储
可以调用webService返回的数据或是解析http协议实现网络数据交互等等 - SQLite存储数据
SQLite是轻量级嵌入式数据库引擎,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。 - ContentProvider
为应用程序之间访问提供的接口组件,实现数据共享结构化数据集合,以表的形式对外提供数据,可以像数据库一样选择排序 - 使用SharedPreferences存储数据
适用范围:保存少量的数据,且这些数据的格式非常简单:字符串型、基本类型的值。比如应用程序的各种配置信息(如是否打开音效、是否使用震动效果、小游戏的玩家积分等),解锁口 令密码等
4.如何启用Service,如何停用Service
首先服务的特点:1 没有界面用户不可见 2 程序在后台运行做耗时操作
服务分三类:startService() bindService() intentService - 使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。
- 采用startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用stopService()方法结束服务,服务结束时会调用onDestroy()方法。
- 采用bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,。接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()–>onDestroy()方法。
- 大部分的service不需要同时处理多个请求(处理多个请求是一个比较危险的多线程场景)这样的情况下最好使用intentService类去实现。原因:intentService会直接创建默认的工作线程,在服务中无须再自己写线程,自带一个重写的onhandleIntent()方法,不会阻塞别的事情,当处理完所有intent后该方法会自动调用stopself()所以不需要手动调用。
- 自定义View是如何绘制到界面上的
我们知道,不管是自定义View还是系统提供的TextView这些,它们都必须放置在LinearLayout等一些ViewGroup中,因此理论上我们可以很好的 理onMeasure(),onLayout(),onDraw()这三个函数:
- View组件及子组建本身大小多少,这由onMeasure()决定;
- View在ViewGroup中的位置如何,这由onLayout()决定;
- 绘制View的内容,onDraw()定义了如何绘制这个View;
invalidate():调用该方法,可以强制重新绘制界面
requestLayout():当前布局大小改变时,可以调用该方法,刷新布局。
- Android中跨进程通信
- 隐式意图
- 广播
- contentProvider
- service(服务)
- aidl跨进程通信 AIDL的英文全称是Android Interface Define Language 当B进程要去调用A进程中的service时,并实现通信,通过AIDL实现Service的跨进程通信(IPC),其实是通过Binder机制来实现的。我们通常都是通过AIDL来操作的之前整理过的一博客做了详细的介绍:http://blog.csdn.net/yshr1991/article/details/51568752
- 利用Messenger信使,与aidl方式的区别就在于AIDL是多线程的,而Messenger是单线程的,也就是说利用Messenger的跨进程通信在消息队列中每次只有一个请求。
8.事件分发机制
9.ListView的优化方案 - 在getView()方法中复用convertView尽可能的少创建view
- 定义一个viewHolder对象,用于缓存显示数据,减少findViewById的次数
- 如果item显示很多,就要考虑分页加载,规定每页加载多少条,每次请求加载多少条,用户拉到列表底部的时候,再去加载接下来的条目。
- Android中动画的使用
- 四种启动模式,结合具体情况分析
- standard
默认模式,可以不用写配置。在这个模式下,每次激活Activity都会默认
创建一个新的Activity实例并放入栈中,可以有多个相同的实例,也允许
多个 相同Activity叠加。
应用场景:Activity可以多次入栈 - singleTop
可以有多个实例,但是不允许多个相同Activity叠加。如果Activity在栈
顶的时候,启动相同的Activity,不会创建新的实例,而会调用其onNewIntent方法,否则会创建新的实例并放入栈顶,即使栈中存在该
Activity的实例,只要是不在栈顶都会创建新的实例
应用场景:栈顶存在则复用,不存在则创建;浏览器的书签界面,
接受通知启动的内容显示界面 - singleTask
若栈中存在activity实例,就会重用该实例(调用其onNewIntent
方法),并将其上的实例移出栈,如果栈中不存在该实例,将会创
建新的实例放入栈中。
应用场景:如果一个activity创建需要占用系统大量的资源(如CPU
, 内存。。。) 就用singleTask;浏览器的Activity不管从多个浏览
器只会启动主界面一次,其余情况都会走onNewIntent方法并会清
空主界面上的其它界面 - singleInstance
单一实例启动模式 Activity会运行在自己的任务栈中,并且这个任
务栈中只有一个实例存在,不允许其它activity在本任务栈中。
应用场景:如果activity在整个手机系统中只允许一个实例存在,
如电话拨打界面。
- 内存泄露和内存溢出的区别
- 内存泄漏:向系统申请了一块内存空间使用new关键字 使用完了没有及时释放掉程序时间越长占用内存越多最终崩溃
- 内存溢出:你要求分配的内存超出了系统能给的,系统不能提供满足需求的内存,还没有new就直接崩溃了。
原因可能存在如下: - 查询数据库时没有关闭游标cursor
- 构造Adapter时,没有复用convertView
- bitmap使用完后,没有recycle()给释放掉
- 使用文件或访问网络资源时未关闭InputStream/OutStream
- 广播退出程序后,未取消注册
13.关于MVC,MVP,MVVM的一点总结和思考
软件的架构方式有很多种,从最开始的MVC模式,演化到MVP,然后到现在的MVVM,在不断的演化过程中其核心的思想就是降低各组件之间的耦合度,使得数据的流向更加的清晰明了。
-
MVC
较为传统和成熟的一种架构方式,最核心的就是通过Control层来进行调控,所有的调度都是由Control来进行处理。其核心的策略简示如下:
优点:优点是对于混乱的软件组织方式有了一个明确的组织方式,通过Control来掌控全局,同时将View展示和Model的变化分离开。
缺点:从图示中也可以看出,在View和Model之间是直接进行交互的,也就是说View和Model之间是可以相互产生影响的,这样在代码中就必然会导致View和Model之间的耦合。 -
MVP
MVC架构方式的变种,使用Presenter来代替Control,而且改变了数据的流向,View和Model之间不再直接进行交互,而是全部通过Presenter来进行。
优点:优点是可以是得整个软件分层清晰,降低耦合度,同时也将Activity从既是Control又是View的境地中解脱出来,只需要单一的负责UI即可,降低了Activity的任务
缺点:缺点是需要加入Presenter来作为桥梁协调View和Model,同时也会导致Presenter变得很臃肿,在维护时比较不方便。而且对于每一个Activity,基本上均需要一个对应的Presenter来进行对应。 -
MVVM
MVVM其实是对MVP的一种改进,他将Presenter替换成了ViewModel,并通过双向的数据绑定来实现视图和数据的交互。也就是说只需要将数据和视图绑定一次之后,那么之后当数据发生改变时就会自动的在UI上刷新而不需要我们自己进行手动刷新。在MVVM中,他尽可能的会简化数据流的走向,使其变得更加简洁明了
优点:可以使得数据流的走向更加的清晰明了,同时也简化了开发,数据和视图只需要进行一次绑定即可。
缺点:目前这种架构方式规范的实现方式比较不完善,常见的就是DataBinding框架
14.Android进程(推送)保活手段
- 黑色保活:不同的app进程,用广播相互唤醒(包括利用系统提供的广播进行唤醒);
- 白色保活:启动前台Service;
- 灰色保活:利用系统的漏洞启动前台Service
思路一:API < 18,启动前台Service时直接传入new Notification();
思路二:API >= 18,同时启动两个id相同的前台Service,然后再将后启动的Service做stop处理。