0.前言
android的基础知识很多,这里只简略的整理一些重点,参考资料结合自己的见解给大家讲讲,前面写了好多篇框架源码解析,这里就不唠叨源码了。
一、Handler
1.Handler、Looper、Message三者关系
(1)Handler:消息辅助类,主要向消息池发送消息和处理相应的消息(sendMessage和handleMessaage)
(2)Looper:不断循环执行从MessageQueue中读取消息,发送给目标处理
(3)Message:需要传送的消息,携带传送的数据
三者关系:
Looper不断循环从消息池中读取消息并分发消息给处理者,没有消息时进入阻塞状态;Handler调用sendMessage方法发送消息(Message)到消息池中,唤醒Looper,Looper不断从消息池中读取消息后调用消息的handleMessage方法处理消息。
2.MessageQueue数据结构
MessageQueue的数据结构为单链表,因其在插入和删除时比较有优势。主要用于向线程池投递消息和取走消息(即MessageQueue.enqueueMessage和MessageQueue.next)
3.子线程中创建Handler
要先调用Looper.prepare()方法,然后才能调用new Handler()创建Handler
4.Handler的Post原理
内部调用sendMessageDelayed()方法,传递使用getPostMessage方法将Runnable对象转换的一条消息。
在Handler的dispatchMessage方法中处理分发的消息时,会检查Message的callBack是否为空,为空则调用handleMessage方法,否则调用handleCallBack方法(此时已经切换到handler所在的线程),handleCallBack里面直接调用message.callback.run()方法,因此可以使用主线程创建的handler的post方法传递Runnable对象来更新UI。
二、Activity
1.启动模式
standard:标准模式,新建的Activity直接在栈中新建一个实例
mainfest中没有配置默认标准模式
singleTop(FLAG_ACTIVITY_SINGLE_TOP):栈顶复用模式,与standard模式相似,不同的是,如果被启动的activity位于栈顶,将直接复用它而不是新建实例。适用于登陆页面、推送通知等
singleTask(FLAG_ACTIVITY_CLEAR_TOP):栈内单例模式,栈内只有一个Activity实例,如果栈内已经存在此Activity的实例,在其他Activity中启动这个activity,将会直接把这个实例上面的其他activity踢出栈GC掉。适用于程序模块逻辑入口如主页面
singleInstance:堆内单例模式,整个手机操作系统里面只有一个实例存在。
适用于诸如来电显示、锁屏等系统应用
2.Intent中标志位设置启动模式
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:对应mainifest中属性为android:excludeFromRecents=true,当用户查看最近任务列表时该task将不会出现在最近任务列表中
FLAG_ACTIVITY_NEW_TASK:需要被启动的activity在manifest文件中配置taskActivity的值,则会在新标记的activity所在taskActivity中压入这个Activity
3.生命周期
正常:
onCreate():activity正在被创建,无法更新UI。
->onStart():activity后台可见,未出现在前台与用户交互
->onResume():activity前台可见
->onPause():activity正在被停止
->onStop():activity即将停止
->onDestroy():activity即将被回收
横竖屏切换:
onCreate()->onStart()->onResume()->onPause()->onStop()->onDestroy()->
onCreate()->onStart()->onResume()
设置configChanges:
onCreate()->onStart()->onResume()
4.Activity的启动流程
三、Fragment
1.生命周期
onAttach():Fragment与Activity关联之后调用
->onCreate():此时Activity的onCreate方法未执行,不能执行与Activity视图层相关的操作。
->onCreateView():自动关联View
->onActivityCreated():activity完成onCreate()回调之后调用,activity的视图层次结构已经准备好了
->onStart()
->onResume()
home:
onPause->onStop
恢复:
onStart->onResume
退出:
onPause->onStop
->onDestroyView:在视图层次结构与Fragment分离之后调用
->onDestroy:不在使用Fragment时调用
->onDetach:解除Fragment与Activity的绑定,释放资源
2.与Activity通信
(1)使用Activity对象引用:
通过接口,生成Fragment时回调Activity
通过传入ViewModel对象,通过ViewModel共享Activity,从而通过Activity实现通信
(2)Fragment Arguments
传递数据到Fragment中
//示例:在Activity中Bundle bundle=newBundle();bundle.putInt("Num",0);myFragment.setArguments(bundle)//在Fragment中获取Bundle bundle=getArguments()
方法与intent通过bundle传递数据类似
四、Service
1.生命周期
startService启动
onCreate()=>onStartCommand()
多次调用onCreate()只有第一次会执行,onStartCommand会执行多次;
stopService结束服务,执行onDestroy方法,并且多次调用stopService时,onDestroy只有第一次会被执行
bindService启动
当onBind()返回值为null时:
onCreate=>onBind
多次调用onCreate()和onBind只在第一次调用被执行。
不为空:
onCreate()=>onBind()=>onServiceConnected()
unbindService结束服务,生命周期执行onDestroy方法,并且unbindService只能调用一次,多次调用会抛出异常unbindService调用时一定要确保服务已经开启,否则会抛出异常。
2.startService和bindService区别
startService开启服务后,与Actively无关联,独立运行
bindService启动服务后,与Activity关联,推出时必须调用unbindService方法否则报ServiceConnection泄露错误。
五、广播Broadcast
1.NormalBroadcast默认广播
使用context.sendBroadcast()方法发送广播,异步接收,无法拦截
2.OrderBroadcast:有序广播
context.sendorderedBroadcast():每次只发送到优先级较高的接收者那里去,由高到低传送,优先级高的接收者有能力终止这个广播。
优先级:setPriority(int priority)
3.静态广播与动态广播
动态注册的动态广播是非常驻广播,随着Activity的生命周期变化需要注册和取消注册,当取消广播注册的代码所在的生命周期不执行时将引发内存泄漏和异常。
静态注册的静态广播是常驻广播,当程序退出后仍然会接受广播。
有序广播中,优先级高的先接收广播,优先级相同的情况下,动态广播优先于静态广播。
优先级相同的同类广播,静态广播先扫描到的优先于后扫描到的,动态广播先注册的优先于后注册的。且动态注册的广播仍然优先于静态注册的广播
4.广播注册流程:
静态注册
(1)扫描应用安装目录:调用PackgeManagerService.scanDirLi(),先扫描系统apk后扫描第三方apk
(2)解析apk:将上步骤扫描到的apk解析出Packge,并将AndroidManifest.xm中的BroadcastReceiver保持下来,按照顺序解析,因此注册顺序决定接收顺序
(3)保存广播:将广播保持到PackgeMannageService的mReceivers中
——可以通过PackgeManagerService.queryIntentReceivers查询intent对应的静态广播
动态注册
context.registerReceiver()
->(实际调用)AMS.registerReceiver
->mReceiverResolver.addFilter()
5.广播发送流程
context.sendBroadcast()
->ActivityManagerNative.getDefault()//即AMS
.broadcastIntent()
->AMS.broadcastIntentLocked:按顺序,先查询动态广播后查询静态广播
(因此动态广播优先于静态广播)
之后将广播包装到BroadcastRecord中放入BroadcastQueue中,
然后从队列中取出广播消息发送给BroadcastReceiver进行并行处理(如动态注册的非有序广播)和串行处理(如有序广播和静态广播)
为方便记忆,这里擅自作了张流程图:
广播注册.png