CSDN博客地址:
创新互联专注于企业成都全网营销、网站重做改版、长垣网站定制设计、自适应品牌网站建设、H5开发、商城系统网站开发、集团公司官网建设、外贸网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为长垣等各大城市提供网站开发制作服务。
一、Android官方推出的百分比布局的使用
1、导入依赖
2、提供了如下的属性
更多请参考: (需要正确上网)
二、Android官方增强版百分比布局的使用——推荐使用
注:在官方的基础上增加了布局PercentLinearLayout,支持百分比设置正方形,未改变官方原有的使用,支持设置字体的百分比,因此更推荐使用
1、导入依赖
2、支持的布局有
3、支持的属性有
4、使用实例
效果图
效果图
效果图
效果好像与直接使用xx%差不多,但是交换过来好像就不一样了
效果图
更多使用请参考:
AIDL-基本使用
AIDL-自定义数据类型
AIDL-修饰符in,out,inout
AIDL-重连方法
AIDL-接口注册/解注册
AIDL-连接池
为什么要特意讲解一下接口的注册与取消注册呢,因为在使用AIDL进程跨进程通信的时候, 每次传递的接口对象在内存中的地址都是不一样的 ,所以在注册了之后,无法使用常规的方式去取消, 因为注册和解注册传递的接口地址都不一样 ,系统无法识别
由于上面的问题,AIDL中提供了一个专门解决上述情况的类 RemoteCallbackList ,其工作原理就是:
首先,在前面讲解 AIDL的基本使用 的基础上先增加新的AIDL接口以及注册和解注册方法:
然后就是 RemoteCallbackList 的使用方法了:
注册/解注册很简单
接着是使用接口的方式:
ps: 需要注意的是 beginBroadcast() 方法和 finishBroadcast() 方法 必须配合使用 ,哪怕只是简单的获取集合大小
使用AIDL进行跨进程间通信中,往往我们是需要注册监听,让服务端通知的,但是服务端也必须提供解注册的方法,不然客户端如果离开某个界面不想再接受消息了,虽然直接离开不做处理客户端这边不会出错,但是服务端那边的监听集合还存在之前的,那么就会浪费系统资源,所以有注册监听的时候,最好也要实现解注册的方法
《Android开发艺术探索》
还记得第一次听到 Coroutines 的时候,纳闷了一下,口瑞停,这是什么新的番号招式(误),之后其实也没有多在意了,好一段时间,因为一个档案的 I/O 会把 UI Thread 卡住,必须要用异步程序去处理,写 Handler Thread 可以避免,这也是最基础的方式,缺点也很明显某些时候还是避不掉,写 RX 又总觉得微妙感觉有点杀鸡用牛刀的感觉,后来看了一下决定用 Coroutines ,于是有了本篇文章。
普通情况下,执行的顺序会是很直白的 functionA() - functionB() - functionC() 。
如果只有一个 thread ,这样很顺畅没问题。
但假如这是一个跑在 main thread 上,而 ·function A· 是需要另一个 thread 的处理结果,而该结果是需要该 thread 耗费长时间作业才可以获得的。这边姑且称为 IO thread 好了。那不就意味着 function A 得等到 IO thread 处理结束并告知结果才能继续执行 function A 乃至 function B 之后才是 function C 呢?
那在等待 function A 的时候 main thread 啥事都不能做,只能 idle 在那边动也不动。
这如果是在 Android main thread 上,这样的行为会让画面 freeze ,时间稍微长一点就会 ANR 被 OS 当作坏掉进行异常排除了。
其实这个异步问题解决方案很多,诸如自己写一个 callback ,或者自干 Handler thread 去控管或者是用 RX ,去订阅之类。某些时候显得不直观,或者使用起来麻烦,总有种杀鸡何需使用牛刀的感觉。
那有没有可能?我就写成上面那样,但是当 function A 在等待 IO thread 时,让 main thread 去做其他的事情,等到 IO thread 结束耗时处理后,再回来继续执行 function A , function B 、 function C 呢?
是的,可以,这个解决方案便是 Coroutine 。
Coroutines ,这个单字会被标成错字,理由是他其实是两个单字合并而成的,分别是 cooperation + routine, cooperation 意指合作,routine 意指例行作业、惯例,照这里直接翻译就会是合作式例行作业。
想到辉夜姬让人想告白提到了惯例行为,也是念作 routine
那我们看到的翻译多半会是协程、协作程序…这样讲没啥前后感,谁协助程序?协助啥程序? 总之就是满头的问号。
这里 routine 指得是程序中被呼叫的 function、method ,也就是说,我们将 function 、method 协同其他更多的 function、method 共同作业这件事情称为 Coroutines 。
协同作业听起来还是很抽象,具体协同什么呢?
这便是 Coroutines 最典型的特色,允许 method 被暂停( suspended)执行之后再回复(resumed)执行,而暂停执行的 method 状态允许被保留,复原后再以暂停时的状态继续执行。
换句话说,就是我在 main thread 执行到 function A 需要等 IO thread 耗时处理的结果,那我先暂停 function A , 协调让出 main thread 让 main thread 去执行其他的事情,等到 IO thread 的耗时处理结束后得到结果后再回复 function A 继续执行,已得到我要的结果,这便是 Coroutines 的概念,这听起来不是很简单了呢?
事实上这个概念早在 1964 年就已经被提出了,而很多语言也都有这样的概念,只是 Android 上头类似的东西一直没有被积极推广,直到 Kotlin 成为官方语言后, Coroutines 以 Support Library 的形式被推广才又在 Android 业界流行起来。
首先,因为 Kotlin 的 Coroutine 并没有包含在原有包装中,而是以 Support Library 的形式提供开发者使用,所以需要另外导入该 Library。
这里选用这个版本进行演示,实际中可以根据自己的需要修改版本。
那因为是在 Android 上使用的, Android 上头的 main thread 跟普通 java 有点不一样,所以还需要另一个 implementation,不然会报错。
导入之后就可以开始使用了。
这边我想做的是画面上有一个会倒数的 Text ,用 Coroutines 可以简单地做到
那跑起来结果就像这样:
这样如果要 Thread 有相同的结果可以写成这样:
这样会有什么问题就是另一个故事了,至少现在这样不会马上出现 Exception (最常见的就是使用者离开画面没多久就出现一个 Exception),不过也并不是说用 Coroutines 就不会发生这些问题,记得这些做法没有什么优劣,差别在都选择就是了。
说回 Coroutines ,那跟 Thread 一样,某些时候我们会想要临时把它停住,那 GlobalScope.launch 会回传一个 Job class 的玩意
想要把它停住的话就用 cancel 即可
Scope 指得是范围, Coroutines 可以作用的范围。在 Main thread 上或是 IO thread 上,又或者希望开更多的 Worker thread,然后是可以在某个控制流(e.g Activity 的生命周期)中可被控制的。
原则上,在 Kotlin 里头使用任何标记 suspend 的 method(后面会提)都会在 Scope 里面,这样才可以控制 Coroutines 的行进与存活与否。
那这边举的例子, GlobalScope 继承自 CoroutineScope 。它是 CoroutineScope 的一个实作,它的概念就是最高层级的 Coroutines ,它的作用的范围伴随着 Application 的生命周期,那其实他的概念与 Dispatch.Unconfined 相同(待会会提到),用他其实可以避免 Coroutines 被过早结束,但也要记得是,这个用法类似直接呼叫静态函数,需要注意。
那如果直接实作 CoroutineScope 呢?
那会要求实作一个 CoroutineContext ,这是什么玩意?指的就是 Coroutines 作用的情景,这边可以指定他是在 Main thread 上或者就直接弄一个 Job 给他:
这样 launch 的时候就会使用这个 Job 来操作了,如果没有特别定义,那这个 Job 就是跑在 Worker thread 上了,用它更新 UI 会出现 Exception ,这方面可以依据自己的需求去做调整。
不过更多时候我会希望他能够跑在 Main Thread 上, Koltinx Coroutine 有提供 CoroutineScope 的实作 - MainScrope
源码的执行是按照一定流程思路进行的,hook就是在源码的执行流程之间插入一步操作,起到拦截,替换的作用;被改变的对象称为hook点,一般将不易发生变化的类作为hook点;
学习hook必须了解代理模式,可以参考我这篇文章: 反射和动态代理
首先需要知道startactivity的流程: Android进阶解密①——activity的启动过程
我们知道startActivity会通过mInstrumentation这个类,我们可以将这个类作为hook点;
自定义一个Instrumentation,在activity的工作过程中通过反射替换原来的Instrumentation,将原来的Instrumentation传到代理类里面,通过method invoke保证原来的功能不变,然后可以添加自己的自定义操作;
首先拿到activity原来的Instrumentation对象,通过原来的Instrumentation构建出一个InstrumentationProxy对象,将Proxy设置给activity,然后只要在startActivity()之前调用这个方法替换就可以了;