1 AsyncTask
简介:
AsyncTask是对Handler与线程池的封装。使用它的方便之处在于能够更新用户界面,当然这里更新用户界面的操作还是在主线程中完成的,但是由于AsyncTask内部包含一个Handler,所以可以发送消息给主线程让它更新UI。另外,AsyncTask内还包含了一个线程池。使用线程池的主要原因是避免不必要的创建及销毁线程的开销。设想下面这样一个场景:有100个只需要0.001ms就能执行完毕的任务,如果创建100个线程来执行这些任务,执行完任务的线程就进行销毁。那么创建与销毁进程的开销就很可能成为了影响性能的瓶颈。通过使用线程池,我们可以实现维护固定数量的线程,不管有多少任务,我们都始终让线程池中的线程轮番上阵,这样就避免了不必要的开销。除了doInBackground方法由AsyncTask内部线程池执行外,其余方法均在主线程中执行。
在Android 4.1版本之前,AsyncTask类必须在主线程中加载,这意味着对AsyncTask类的第一次访问必须发生在主线程中;在Android 4.1以及以上版本则不存在这一限制,因为ActivityThread(代表了主线程)的main方法中会自动加载AsyncTask
AsyncTask对象必须在主线程中创建
AsyncTask对象的execute方法必须在主线程中调用
一个AsyncTask对象只能调用一次execute方法
AsyncTask内部维护了一个线程池,是串行还是并行,怎么维护的?
串行
2 RecyclerView的拖拽怎么实现的
google ItemTouchHelper
https://www.jianshu.com/p/2067750e9530
3 service两种启动方式有什么区别?
采用start的方式开启服务:
1.定义一个类继承Service
2.在Manifest.xml文件中配置该Service
3.使用Context的startService(Intent)方法启动该Service
4.不再使用时,调用stopService(Intent)方法停止该服务
使用这种start方式启动的Service的生命周期如下:
onCreate()--->onStartCommand()(onStart()方法已过时) --->onDestory()
说明:如果服务已经开启,不会重复的执行onCreate(), 而是会调用onStart()和onStartCommand()。
服务停止的时候调用onDestory()。服务只会被停止一次。
特点:一旦服务开启跟调用者(开启者)就没有任何关系了。
开启者退出了,开启者挂了,服务还在后台长期的运行。
开启者不能调用服务里面的方法。
采用bind的方式开启服务:
1.定义一个类继承Service
2.在Manifest.xml文件中配置该Service
3.使用Context的bindService(Intent, ServiceConnection, int)方法启动该Service
4.不再使用时,调用unbindService(ServiceConnection)方法停止该服务
使用这种start方式启动的Service的生命周期如下:
onCreate()--->onBind()--->onunbind()--->onDestory()
注意:绑定服务不会调用onstart()或者onstartcommand()方法,bind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。
绑定者可以调用服务里面的方法。
4 Handler机制
1、handler封装消息的发送(主要包括消息发送给谁)
2、Looper——消息封装的载体。(1)内部包含一个MessageQueue,所有的Handler发送的消息都走向这个消息队列;(2)Looper.Looper方法,就是一个死循环,不断地从MessageQueue取消息,如果有消息就处理消息,没有消息就阻塞。
3、MessageQueue,一个消息队列,添加消息,处理消息
4、handler内部与Looper关联,handler->Looper->MessageQueue,handler发送消息就是向MessageQueue队列发送消息。
总结:handler负责发送消息,Looper负责接收handler发送的消息,并把消息回传给handler自己。 MessageQueue存储消息的容器。
5-LRUCache原理
https://www.jianshu.com/p/b49a111147ee
6-模块化实现(好处,原因)
为什么模块间解耦,复用?
原因:对业务进行模块化拆分后,为了使各业务模块间解耦,因此各个都是独立的模块,它们之间是没有依赖关系。每个模块负责的功能不同,业务逻辑不同,模块间业务解耦。模块功能比较单一,可在多个项目中使用。
为什么可单独编译某个模块,提升开发效率?
原因:每个模块实际上也是一个完整的项目,可以进行单独编译,调试
为什么可以多团队并行开发,测试?
原因:每个团队负责不同的模块,提升开发,测试效率
7统计启动时长,标准
adb shell am start -w pageage/activityname 通过这条命令启动,可以获得启动时间
8classloader 类加载器
9动态布局
// 第一种 View layoutView = View.inflate(this, R.layout.activity_main ,null) ;
// 第2种 layoutView = LayoutInflater.from(this).inflate(R.layout.activity_main ,null) ;
// 第3种 layoutView = LayoutInflater.from(this).inflate(R.layout.activity_main ,null,false) ;
10 热修复
11插件化
12 性能优化,怎么保证应用启动不卡顿
13 SP是进程同步的吗?有什么方法做到同步
SharedPreferences不支持进程同步.考虑用ContentProvider来实现SharedPreferences的进程同步.
14介绍下SurfView
首先SurfaceView也是一个View,它也有自己的生命周期。因为它需要另外一个线程来执行绘制操作,所以我们可以在它生命周期的初始化阶 段开辟一个新线程,然后开始执行绘制,当生命周期的结束阶段我们插入结束绘制线程的操作。这些是由其内部一个SurfaceHolder对象完成的。 SurfaceView它的绘制原理是绘制前先锁定画布(获取画布),然后等都绘制结束以后在对画布进行解锁 ,最后在把画布内容显示到屏幕上。
SurfaceView相当于是另一个绘图线程,它是不会阻碍主线程,并且它在底层实现机制中实现了双缓冲机制。
15 Bundle 机制
16 android 事件传递机制
17 App启动流程,从点击桌面开始
18 什么情况下会出现ANR问题:
输入事件(按键和触摸事件)5s内没被处理
BroadcastReceiver的事件(onRecieve方法)在规定时间内没处理完(前台广播为10s,后台广播为60s)
service 前台20s后台200s未完成启动
ContentProvider的publish在10s内没进行完:timeout publishing content providers
分析:
主线程在做一些耗时的工作
主线程被其他线程锁
cpu被其他进程占用,该进程没被分配到足够的cpu资源。
从log中找到ANR反生的信息:可以从log中搜索“ANR in”或“am_anr”,会找到ANR发生的log,该行会包含了ANR的时间、进程、是何种ANR等信息,
在该条log之后会有CPU usage的信息,表明了CPU在ANR前后的用量(log会表明截取ANR的时间),从各种CPU Usage信息中大概可以分析如下几点:
(1). 如果某些进程的CPU占用百分比较高,几乎占用了所有CPU资源,而发生ANR的进程CPU占用为0%或非常低,则认为CPU资源被占用,进程没有被分配足够的资源,从而发生了ANR。这种情况多数可以认为是系统状态的问题,并不是由本应用造成的。
(2). 如果发生ANR的进程CPU占用较高,如到了80%或90%以上,则可以怀疑应用内一些代码不合理消耗掉了CPU资源,如出现了死循环或者后台有许多线程执行任务等等原因,这就要结合trace和ANR前后的log进一步分析了。
(3). 如果CPU总用量不高,该进程和其他进程的占用过高,这有一定概率是由于某些主线程的操作就是耗时过长,或者是由于主进程被锁造成的。
除了上述的情况(1)以外,分析CPU usage之后,确定问题需要我们进一步分析trace文件。trace文件记录了发生ANR前后该进程的各个线程的stack。对我们分析ANR问题最有价值的就是其中主线程的stack,一般主线程的trace可能有如下几种情况:
(1). 主线程是running或者native而对应的栈对应了我们应用中的函数,则很有可能就是执行该函数时候发生了超时。
(2). 主线程被block:非常明显的线程被锁,这时候可以看是被哪个线程锁了,可以考虑优化代码。如果是死锁问题,就更需要及时解决了。
(3). 由于抓trace的时刻很有可能耗时操作已经执行完了(ANR -> 耗时操作执行完毕 ->系统抓trace)
链接:https://www.jianshu.com/p/fa962a5fd939
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
网友评论