扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
1: 分屏模式:
专注于为中小企业提供成都网站设计、网站建设、外贸网站建设服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业南城免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了成百上千企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
该模式可以在手机上使用, 该模式将屏幕一分为二, 同时显示两个应用界面
2: 画中画模式:
该模式主要用于TV, 在该模式下视频播放的窗口可以一直在最顶端显示。(视频小窗口)
3: Freeform模式:
该模式类似于常见的桌面操作系统, 应用界面的窗口可以自由的拖动和修改大小
1:Manifest 新增属性:
2: layout 新增属性:
在freeform模式下定义的默认高度和宽度defaultWidthdefaultHeight, freeform模式下的初始Gravity, freeform模式下最小高度和宽度minWidthdefaultHeight。
3: 多窗口的API:
4: 分屏模式的生命周期:
很明显, 从上图的生命周期显示, 在后台将应用进入分屏模式的时候, 先执行destroy()的方法, 即在进入分屏之前, activity会被先销毁,再调用onRestoreInstanceState方法恢复数据, 回调onMultiWindowModeChanged()
我们的 APP 进入分屏模式时,在 onMultiWindowModeChanged 方法中如果有对 UI 等的操作,经过之后的自动重建就没有效果了。为了防止这种情况,需要在 AndroidManifest.xml 的 Activity 节点设置以下属性:android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
设置了这个属性,在进入分屏模式时,Activity 就不会自动重建了。
5 跨Activity对View的拖拽:
Android 4.0 开始支持activity内容的拖拽, 在多窗口的模式下,Android也实现了activity间 实现内容的拖拽。在activity间仅限于内容的拖拽, 对view的拖拽也是没办法实现的 。
类似微信视频、语音时点击返回会形成一个App小窗口浮动在界面上,点击继续是通通话,如下图:
其实实现这个功能只需要你细心分析一下就有思路了:首先这个小窗口是浮动在app最上层的视图,其次所有触屏事件需先由该小窗口处理,还有就是小窗口的生命周期和Application也能虽可能不能同生,但是确是可以共死。所以可以在Application中创建一个view添加到WindowManage,这里将视图为view的window的type设置成系统级别的窗口,这样这个window可以在在全局呈现。另外,还需要让这个window可以随手指拖动而滑动,手指释放后会回弹到距离这个释放点最近的屏幕侧边,所以需要重写view 的OnTouch事件。
以上就能实现一个应用内小窗口了,这里windowManager的布局参数有坑要踩:
这里主要探讨Touchable,Focusable,OutsideTouchable,TouchModal这四个混合使用的效果。
最简单的Touchable,
为false,表示窗口不接受触摸事件;
为true,表示窗口接受触摸事件;
要窗口接收事件,必须为true。窗口不接受事件,意味着事件会透传到下一个窗口。这里的窗口事件是指DOWN-UP,窗口是指窗口自身范围,窗口外的ACTION_OUTSIDE与此设置无关。
为false,表示对ACTION_OUTSIDE事件不感兴趣。
为true,表示对ACTION_OUTSIDE事件感兴趣,此时, 如果新事件被另一个窗口消化 ,则会发送ACTION_OUTSIDE给该窗口。包括:
2.1. 如果窗口设置了Touchable为false。即使触摸事件在窗口内,由于不处理事件,导致事件透传,被另一个窗口消化,此时该窗口也会收到ACTION_OUTSIDE。
2.2 触摸事件在窗口外面触发,导致事件被另一个窗口消化,此时该窗口也会收到ACTION_OUTSIDE。
2.3 如果窗口设置了TouchModal和Focusable,导致窗口内外的事件被当前窗口截获,由于不是被另一个窗口消化,所以即使设置了OutsideTouchable,也不会有ACTION_OUTSIDE。
为false,表示不会聚焦,所以不会有软键盘。同时它的z-order可以在软键盘之上,覆盖软键盘。如果你在不聚焦的情况下,还需要软键盘,可以使用FLAG_ALT_FOCUSABLE_IM来修改。 如果为false,会放弃TouchModal原来的值,强制设置TouchModal为false
为true,表示窗口可以聚焦。
TouchModal的设置,只有在Focusable为true时才有效,Focusable为false,会忽略TouchModal的值
为true,当窗口Focusable为true时,无论窗口内外,事件都被当前窗口接收。
为false,当窗口Focusable为true时,只有窗口内的事件被当前窗口接收。窗口外,OutsideTouchable的设置决定了是否有ACTION_OUTSIDE事件。
为true,当窗口Focusable为false时,设置不生效。
为false,当窗口Focusable为false时,设置不生效。
FLAG_NOT_TOUCHABLE,意味着,默认是TOUCHABLE,必要时,才使用这个Flag关闭。
FLAG_NOT_FOCUSABLE,意味着,默认是FOCUSABLE,必要时,才使用这个Flag关闭。
FLAG_WATCH_OUTSIDE_TOUCH,意味着,默认是不关心,必要时,才使用这个Flag开启。
FLAG_NOT_TOUCH_MODAL,意味着,默认是TOUCH_MODAL,必要时,才使用这个Flag关闭。
FLAG_NOT_FOCUSABLE的注释是这样的。This flag will also enable FLAG_NOT_TOUCH_MODAL whether or not that is explicitly set.
所谓的enable,就是使用这个Flag 。直接翻译就是,使用了FLAG_NOT_FOCUSABLE这个Flag,就会同时使用FLAG_NOT_TOUCH_MODAL这个flag。
使用FLAG_NOT_FOCUSABLE就是关闭FOCUSABLE,使用FLAG_NOT_TOUCH_MODAL就是关闭TOUCH_MODAL。简述就是,关闭了FOCUSABLE,会同时关闭TOUCH_MODAL。
比如,Touchable,当一个事件确实派发到窗口到时候,就看这个Flag,为true就是接受事件,为false就是不接受事件。你可以提前截获不让事件派发到窗口,但一旦派发到窗口,就是这个Flag来决定窗口是否接受事件。
比如,OutsideTouchable,你可以截获事件不让事件派发到另一个窗口,但一旦事件派发到另一个窗口,就是这个Flag决定当前窗口是否接受ACTION_OUTSIDE事件。
以下,窗口内外是指,触点在窗口内/外。完整事件是指DOWN to UP事件流。ACTION_OUTSIDE事件只有一次。
总结, Touchable和OutsideTouchable分别控制了窗口内外的事件 。
总结, 当且仅当Focusable为true,TouchModal为true情况下,窗口内外事件才被当前窗口截获;否则,都是窗口内才有完整事件,窗口外才有ACTION_OUTSIDE事件 。
Activity是一个 界面 的载体,可以把它与html页面进行类比,html页面由各种各样的标签组成,而Activity则可以由 各种控件 组成。
Activity的掌握重点主要在于:
a.Activity的生命周期
b.Activity的启动模式
onCreate() :
当Activity第一次被创建的时候调用此方法.一般在此方法中 进行控件的声明,添加事件等初始化工作 .
onStart():
当Activity被显示到屏幕上的时候调用此方法,执行完此方法后 界面可见
onResume():
当此Activity能够被操作之前,也就是能够获得用户的焦点之前调用此方法.
onRestart():
当Activity被停止后又被再次启动之前调用此方法.接着将调用onStart()方法.
onPause():
当第一个Activity通过Intent启动第二个Activity的时候,将调用第一个Activity的onPause()方法.然后调用第二个Activity的onCreate(),onStart(),onResume()方法,接着调用第一个Activity的onStop()方法.如果Activity重新获得焦点,则将调用onResume()方法;如果此Activity进入用户不可见状态,那么将调用onStop()方法.
onStop():
当第一个Activity被第二个Activity完全覆盖,或者被销毁的时候回调用此方法.如果此Activity还会与用户进行交互,将调用onRestart方法();如果此Activity将被销毁,那么将调用onDestroy()方法.
注意:
a.home键返回,锁屏,关闭界面肯定会调用onStop方法
b.但是开启另一个Activity并不一定会调用onStop方法
onDestroy():
Activity被销毁之前调用此方法.或者是调用finish()方法结束Activity的时候调用此方法.可以在此方法中进行收尾工作,比如释放资源等.
Active/Runing 一个新 Activity 启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态。
Paused 当 Activity 被另一个透明或者 Dialog 样式的 Activity 覆盖时的状态。此时它依然与窗口管理器保持连接,系统继续维护其内部状态,所以它仍然可见,但它已经失去了焦点故不可与用户交互。
Stoped 当 Activity 被另外一个 Activity 覆盖、失去焦点并不可见时处于 Stop ed 状态。
Killed Activity 被系统杀死回收或者没有被启动时处于 Killed 状态。
在 manifest 文件中声明 activity 时,利用activity元素的 launchMode 属性来设定 activity 与 task 的关系。
launchMode 属性 指明了 activity 启动 task 的方式,默认 standard方式
standard(默认模式):
系统在启动 activity 的 task 中创建一个新的 activity 实例,并把 intent 传送路径指向它。 该 activity 可以被实例化多次,各个实例可以属于不同的 task,一个 task 中也可以存在多个实例。
singleTop:
如果 activity 已经存在一个实例并位于当前 task 的 栈顶 ,则系统会调用已有实例的 onNewIntent() 方法把 intent 传递给已有实例,而不是创建一个新的 activity 实例。activity 可以被实例化多次,各个实例可以属于不同的 task,一个 task 中可以存在多个实例(但仅当 back stack 顶的 activity 实例不是该 activity 的)。
singleTask:
系统将创建一个新的 task,并把 activity 实例 作为根 放入其中。但是,如果 activity 已经在其它 task 中存在实例,则系统会通过调用其实例的onNewIntent() 方法把 intent 传给已有实例,而不是再创建一个新实例。 此 activity 同一时刻只能存在一个实例。
例如:可以用于关闭所有Activity或重新登录等
singleInstance:
除了系统不会把其它 activity 放入当前实例所在的 task 之外,其它均与"singleTask"相同。activity 总是它所在 task 的唯一成员;它所启动的任何 activity 都会放入其它 task 中
主要是startActivity(intent),或者带值返回startActivityForResult(intent) , Activity的跳转方式 。
1、ViewRoot 对应于 ViewRootImpl 类,它是连接 WindowManager 和 DecorView 的纽带,View 的三大流程均是通过 ViewRoot 来完成的。在 ActivityThread 中,当 Activity 对象被创建完毕后,会将 DecorView 添加到 Window 中,同时会创建 ViewRootImpl 对象,并将 ViewRootImpl 对象和 DecorView 建立关联
2、 自定义View-绘制流程概述
4、 Android Handler
6、 Android Bitmap
2、MeasureSpec:
3、一般来说,使用多进程会造成以下几个方面的问题:
5、Window 概念与分类:
Window 是一个抽象类,它的具体实现是 PhoneWindow。WindowManager 是外界访问 Window 的入口,Window 的具体实现位于 WindowManagerService 中,WindowManager 和 WindowManagerService 的交互是一个 IPC 过程。Android 中所有的视图都是通过 Window 来呈现,因此 Window 实际是 View 的直接管理者。
6、window的三大操作:addView、upView、removeView
7、 Bitmap 中有两个内部枚举类:
保存图片资源:
图片压缩:
基本使用:
8、Context 本身是一个抽象类,是对一系列系统服务接口的封装,包括:内部资源、包、类加载、I/O操作、权限、主线程、IPC 和组件启动等操作的管理。ContextImpl, Activity, Service, Application 这些都是 Context 的直接或间接子类
9、SharedPreferences 采用key-value(键值对)形式, 主要用于轻量级的数据存储, 尤其适合保存应用的配置参数, 但不建议使用 SharedPreferences 来存储大规模的数据, 可能会降低性能
10、SharedPreferences源码有用synchronize进行加锁同步
11、Handler 有两个主要用途:
(1)安排 Message 和 runnables 在将来的某个时刻执行;
(2)将要在不同于自己的线程上执行的操作排入队列。(在多个线程并发更新UI的同时保证线程安全。)
只有主线程能对UI进行操作,所以在对UI进行跟改之前,ViewRootImpl 对UI操作做了验证,这个验证工作是由 ViewRootImpl的 checkThread 方法完成:
12、ThreadLocal 是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,其他线程则无法获取。Looper、ActivityThread 以及 AMS 中都用到了 ThreadLocal。当不同线程访问同一个ThreadLocal 的 get方法,ThreadLocal 内部会从各自的线程中取出一个数组,然后再从数组中根据当前 ThreadLcoal 的索引去查找对应的value值:
13、Android 提供了几种途径来从其他线程访问 UI 线程:
Android单线程模式必须遵守的规则:
14、HandlerThread 集成了 Thread,却和普通的 Thread 有显著的不同。普通的 Thread 主要用于在 run 方法中执行一个耗时任务,而 HandlerThread 在内部创建了消息队列,外界需要通过 Handler 的消息方式通知 HanderThread 执行一个具体的任务。
15、IntentService 可用于执行后台耗时的任务,当任务执行后会自动停止,由于其是 Service 的原因,它的优先级比单纯的线程要高,所以 IntentService 适合执行一些高优先级的后台任务。在实现上,IntentService 封装了 HandlerThread 和 Handler。IntentService 第一次启动时,会在 onCreatea 方法中创建一个 HandlerThread,然后使用的 Looper 来构造一个 Handler 对象 mServiceHandler,这样通过 mServiceHandler 发送的消息最终都会在 HandlerThread 中执行。每次启动 IntentService,它的 onStartCommand 方法就会调用一次,onStartCommand 中处理每个后台任务的 Intent,onStartCommand 调用了 onStart 方法。可以看出,IntentService 仅仅是通过 mServiceHandler 发送了一个消息,这个消息会在 HandlerThread 中被处理。mServiceHandler 收到消息后,会将 Intent 对象传递给 onHandlerIntent 方法中处理,执行结束后,通过 stopSelf(int startId) 来尝试停止服务。(stopSelf() 会立即停止服务,而 stopSelf(int startId) 则会等待所有的消息都处理完毕后才终止服务)。
16、RecyclerView 优化
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流