对于Activity与Fragment直接的相互调用:
1、Activity调用Fragment直接调用就好了,Activity一般是持有Fragment实例的。或者通过Fragment的id或者tag获取Fragment的实例
2、Fragment调用Activity,使用回调或者getActivty()获取activity的实例
数据传递:
1、Activity传递给fragment,使用bundle添加然后setArgument传递。
2、广播
3、handler
4、EventBus
5、ViewModel实现数据共享
Standard:默认的启动模式,页面创建的时候一直压栈
SingleTop:栈顶跳转模式,跳转页面的时候判断如果栈顶有这个页面,则这个页面上的所有页面进行出栈。如果栈顶没有这个页面则重新创建。
SingleTask:站内跳转模式,主要应用于首页。跳转页面的时候判断站内有这个页面则这个页面上的所有页面出栈。如果栈内没有则重新创建。
SingleInstance:独立站模式,把页面设置成这个模式会变成一个独立的进程。假设ABC三个页面B页面是这个模式,A->B->C跳转,返回的时候则是C->A
BroadcaseRecevier:是跨应用广播,使用Binder来实现,支持动态和静态注册
LocalBroadcaseRecevier:应用内广播,Handler来实现的,应用内效率高更安全,仅支持动态注册
0、Context是一个抽象类,在安卓中代表我们的上下文
1、Content主要是获取系统信息,访问资源,信息存储,AMS的交互
2、ContentImpl是具体的实现类,Activity,Service,Application本质就是Context都包含这个ContentImpl类,委托他获取资源
3、Context的数量:Activity+Service+Application(1)
4、ContentWrapper是Context的包装类,其实也是委托ContextImpl来实现的
5、ContextImpl是上下文的核心空间,可以实现安卓平台的通信,比如startActivity
IntentFilter是Intent隐式跳转的配置,分为3种匹配规则:action\category\data
action:intent-filter可以多个,Intent只能一个。如果Intent-filter不配置action,Intent无法通过。如果配置了action,那么Intent不配置action可以通过,如果Intent配置了action则必须是IntentFilter其中的一个,区分大小写
category:2者都可以多个,如果IntentFilter不配置则所有的Intent无法通过,因为有默认的。IntentFilter配置category,Intent不配置可以通过,如果配置则必须是IntentFilter配置的子集。
data:IntentFilter可以配置多个,Intent只能一个。如果通过2者必须精准匹配一模一样
匹配机制:IntentFilter必须满足其中一组的action、category、data全部通过。同一个应用尽量使用显示意图跳转
1、执行startService时,Service会经历onCreate->onStartCommand。当执行stopService时,直接调用onDestroy方法。调用者如果没有stopService,Service会一直在后台运行,下次调用者再起来仍然可以stopService。
2、执行bindService时,Service会经历onCreate->onBind。这个时候调用者和Service绑定在一起。调用者调用unbindService方法或者调用者Context不存在了(如Activity被finish了),Service就会调用onUnbind->onDestroy。这里所谓的绑定在一起就是说两者共存亡了。
3、多次调用startService,该Service只能被创建一次,即该Service的onCreate方法只会被调用一次。但是每次调用startService,onStartCommand方法都会被调用。Service的onStart方法在API 5时被废弃,替代它的是onStartCommand方法。
4、第一次执行bindService时,onCreate和onBind方法会被调用,但是多次执行bindService时,onCreate和onBind方法并不会被多次调用,即并不会多次创建服务和绑定服务。
onBind回调方法将返回给客户端一个IBinder接口实例,IBinder允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。我们需要IBinder对象返回具体的Service对象才能操作,所以说具体的Service对象必须首先实现Binder对象。
如果一个Service又被启动又被绑定,则该Service会一直在后台运行。首先不管如何调用,onCreate始终只会调用一次。对应startService调用多少次,Service的onStartCommand方法便会调用多少次。Service的终止,需要unbindService和stopService同时调用才行。不管startService与bindService的调用顺序,如果先调用unbindService,此时服务不会自动终止,再调用stopService之后,服务才会终止;如果先调用stopService,此时服务也不会终止,而再调用unbindService或者之前调用bindService的Context不存在了(如Activity被finish的时候)之后,服务才会自动停止。
那么,什么情况下既使用startService,又使用bindService呢?
1、如果你只是想要启动一个后台服务长期进行某项任务,那么使用startService便可以了。如果你还想要与正在运行的Service取得联系,那么有两种方法:一种是使用broadcast,另一种是使用bindService。前者的缺点是如果交流较为频繁,容易造成性能上的问题,而后者则没有这些问题。因此,这种情况就需要startService和bindService一起使用了。
2、另外,如果你的服务只是公开一个远程接口,供连接上的客户端(Android的Service是C/S架构)远程调用执行方法,这个时候你可以不让服务一开始就运行,而只是bindService,这样在第一次bindService的时候才会创建服务的实例运行它,这会节约很多系统资源,特别是如果你的服务是远程服务,那么效果会越明显(当然在Servcie创建的是偶会花去一定时间,这点需要注意)。
本地服务依附在主进程上,在一定程度上节约了资源。本地服务因为是在同一进程,因此不需要IPC,也不需要AIDL。相应bindService会方便很多。缺点是主进程被kill后,服务变会终止。
远程服务是独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是独立的进程,因此在Activity所在进程被kill的是偶,该服务依然在运行。缺点是该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点。
对于startService来说,不管是本地服务还是远程服务,我们需要做的工作都一样简单。
1、和系统厂商合作加入白名单
2、息屏的时候启动1px像素的activity,Service中循环播放静音的音频提高优先级
3、谷歌推荐的是前台服务的保活,但是会有通知栏
4、全家桶,相互发系统广播做服务的拉起
当程序A想把数据共享给程序B的时候,用到ContentProvider实现数据共享,程序B不管程序A是否启动使用ContentResolver实现数据的增删改查
ContentProvider以URI提供数据,ContentResolver也是以URI实现数据访问
竖屏: 启动:onCreat->onStart->onResume. 切换横屏时: onPause-> onSaveInstanceState ->onStop->onDestory
onCreat->onStart->onSaveInstanceState->onResume.
但是,我们在如果配置这个属性:android:configChanges="orientation|keyboardHidden|screenSize" 就不会在调用Activity的生命周期,只会调用onConfigurationChanged方法
当Activity设置为SingleTask或者SingleTop的时候,页面再次被跳转的时候,不会重新创建。此时在onNewIntent方法中获取传参
Intent基于Binder,Intent数据会存储在Bundle中,小于1M
可以用本地数据存储,或者eventbus等方式
ContentResolver实现ContengProviver共享来的数据,同时注册ContentObserver实现数据的监听
HandlerThread是Handler的一个封装体,线程有了自己的Loop这样就可以进行一个绑定。在我们不需要读取消息队列的时候就对线程进行quit就可以了
IntentService
是Service
的子类,默认为我们开启了一个工作线程,使用这个工作线程逐一处理所有启动请求,在任务执行完毕后会自动停止服务,使用简单,只要实现一个方法onHandleIntent
,该方法会接收每个启动请求的Intent
,能够执行后台工作和耗时操作。可以启动IntentService
多次,而每一个耗时操作会以队列的方式在 IntentService 的onHandlerIntent
回调方法中执行,并且,每一次只会执行一个工作线程,执行完第一个再执行第二个。并且等待所有消息都执行完后才终止服务。
IntentService
适用于 APP 在不影响当前用户的操作的前提下,在后台默默的做一些操作。IntentService源码:
- 通过
HandlerThread
单独开启一个名为IntentService
的线程- 创建一个名叫
ServiceHandler
的内部Handler
- 把内部Handler与HandlerThread所对应的子线程进行绑定
- 通过
onStartCommand()
传递给服务intent
,依次插入到工作队列中,并逐个发送给onHandleIntent()
- 通过
onHandleIntent()
来依次处理所有Intent
请求对象所对应的任务
是重新创建了一个Runnable对象,使其绑定到主线程。在runOnUiThread方法中,判断如果在主线程了只能run。如果不在则handler会将runnable post到looper中,而handler则是绑定主线程的Looper,就会在主线程中执行代码
极端情况下可以在页面加载之前进行绘制,onCreate,onStart,onResums. 因为此时的主线程还没有进行UI的绘制
在主线程中创建Handler对象,重新handleMessage()方法. 在子线程中创建Message对象,并使用Handler对象将其发送到MessageQueue中,Looper会一直尝试抓起队列中的消息,然后将其发送给Handler的handleMessage方法
因为在主线程中创建Handler会自动绑定主线程中的Looper,但是子线程中没有开启Looper也没有进行Looper绑定,所以会报错
1、可以在子线程中Looper.loop() 去开启,这样runnable运行在子线程,但是runable中不可以更新UI只能做联网操作
2、可以子线程中的handler去绑定主线程的Looper,这样runnable运行在主线程,这样可以更新UI但是不能联网
补间动画:平移、旋转、透明度和缩放。只能作用在view上,不会改变view的属性,,复杂的动画能力差,使用范围也一般
属性动画:完全包含了补间动画,平移旋转缩放透明度能实现外,还可以组合,抛物线等等,他可以作用任何对象上,会改变对象的属性值,复杂的动画能力强,使用范围大
window:是windowManager管理的最顶级的view,他负责的是窗口(背景)。他是个抽象类,实现类是phoneWindow.
DecorView:是view的根节点,里面是一个竖向的LinearLayout 分为上下2个部分,上面是titleBar,下面是contentParent. 实现Activity就是在contentParent中。所有的view事件都是要经过DecorView然后在给到View中。
联系:DecorView是window的一个属性,所以是被widow持有的。view是通过DecorView加载的,DecorView是被window持有渲染显示的。
绘制效率:FrameLayout>LinearLayout>RelativeLayout. 因为FrameLayout只需要一层层的放上去就好了。LinearLayout是2个方向的。RelativeLayout是根据id计算的
工作效率:每个使用场景不同,不同场景使用不用的布局方式,不存在工作效率比较
1、触发过程:Activity->Window->DocerView->ViewGroup->View,View不触发再返回由父级处理依次向上推。 2.在每个阶段都要经过三个方法 dispatchTouchEvent(分发)、onInterceptTouchEvent(拦截)、onTouch(处理)
大体流程: Activity中走了Window 的 dispatch,Window 的 dispatch 方法直接走了 DocerView 的 dispatch 方法,DocerView 又直接分发给了 ViewGroup,ViewGroup 中走的是 onInterce 判断是否拦截,拦截的话会走 onTouch 来处理,不拦截则继续下发给 View。到 View 这里已经是最底层了,View 若继续不处理,那就调用上层的 onTouch 处理,上层不处理继续往上推。
1、onGlobalLayoutListener
2、onPerDrawLauyoutListener
3、onLayoutChangeListener
4、view.post
5、重写view中onSizeChange()方法
插值器:根据时间流逝的百分比来计算属性变化的百分比,系统有加速的、减速的或者加减速的
估值器:就是属性百分比的具体值。系统有整数的、浮点数或者是颜色估值器。
通过XML解析器获取标签的名字,然后去走createview去根据类的全路径,再然后去进行反射创建出类。
正常的Fragment默认都会有一个预加载的页面,其实就是同时加载了2个。解决这个问题2种方法
1、在setVisbleHint()方法中判断是否是第一次加载或者页面的可见状态
2、androidX后第一个方法就没有用了, setMaxLifeCycler(START) 这个方法可以设置fragment显示到onStart().我们不显示的frgament不去加载数据,只有显示的fragment在onResume种网络请求
invalidate():绘制UI的方法,在UI线程中调用
postinvalidate():绘制UI的方法,可以在UI线程或者子线程中调用,因为他内部使用的是Handler所以会帮我们切换线程,实际上还是在主线程中更新的UI
SurfaceView:是可以在子线程刷新的view,不同于其他view没有动画view的特性也没有
TextrueView:是SurfaceView的升级,具备View的特性可以平移,缩放等
Window是窗口,对Activty,Dialog,Toast等的展示。但是他是个抽象类,具体实现是phoneWindow类.外界访问window的入口是通过windowManger. windowManager和windowMangerService是通过IPC通讯的,从而来管理window
window下面是DocerView,DocerView里面有包含了View,所以view是window的体现,window是view的承载。windowManager则可以操作view:addView,removeView和updateViewLayout
window:窗口,phoneWindow是具体的实现类,外部通过windowManager来管理。window和view通过ViewRootImpl进行管理
View:视图
Activity:用来进行视图显示的
三者的关系:
activity创建的时执行attach()来创建phoneWindow,activity和Window进行绑定,activity实现Window的CallBack,当window收到外界改变的时候就会回调给activity来执行。window创建的时候会创建DecorView,他是view的根节点,里面包含了竖向Linealayout,里面是titleBar和contentParent。 DecorView来加载我们的布局文件,然后将activity的视频加载到我们的contentParent上。
activity是通过window来管理view的展示。一个activity对应一个window,一个window对应一个View.
1、设置margin
2、滑动平移
3、seTranslationX,seTranslationY
4、offsetTopAndButtom,offsetLeftAndRight
5、scorllBy,scorllTo
因为被上一级的viewpager拦截掉了,需要做滑动冲突处理,重写子类的dispachTouchEvent方法
判断当前页是0或者最后一页,父级处理,否则自己处理
生命周期:
onAttach->onCraete->onCreateView->onActivityCreate->onStart->onResume->onPause->onStop->onDestoryView-onDestory
Frgament在ViewPager中的生命周期:因为viewpager配合fragment使用的时候有预加载页面的功能,所以相邻的fragment是已经创建完毕了。切换后不相邻的执行onPause->onStop->onDestoryView
fragment直接数据传递:
1、创建的时候构造方法
2、Bundle传参
3、EventBus
4、回调接口
单Activity多Fragment的优缺点
fragment比activity占用更少的内存空间,使用流畅,更容易控制各个场景是生命周期
优缺点:使用灵活,内存占用低。但是必须依赖Activity,生命周期受Activty的影响