0%

背景

WebView​作为承载动态页面的容器,在安卓中本身只是一个用于加载​web​页面的视图控件,但​web​页面中常需要与​Native​进行交互动作,比如跳转到一个​Native​页面、弹出一条​Toast​提示、检测设备状态等。

在更加复杂的情境中:

  • 小程序
    • 需要根据​web​的需要在​WebView​上覆盖显示一些​Native​控件以提供接近​native​的体验(​input​框、地图等)
    • 提供一些诸如本地储存、定位数据之类的服务供​web​使用(虽然部分走的是​V8​引擎,但仍需要​JSBridge​去进行一些通信)
  • Hybrid应用
    • ​Native​控件与​web​频繁交互
    • ​Native​页面/组件利用​JSBridge​与后端同步数据,简化后端工作量(不需要维护两套通信接口),但过度依赖于​WebView​

以上通信的基础设施就是​JSBridge​,​JSBridge​的实现本身并不复杂,可以看作是对系统接口的二次封装。

阅读全文 »

Backgroud/Target

由Jetbrains在圣彼得堡的团队开发,得名于附近的一个Kotlin的小岛。

Jetbrains有多年的Java平台开发经验,他们认为Java编程语言有一定的局限性,而且由于需要向后兼容,它们很难得到解决。因此,他们创建了Kotlin项目,主要目标包括:

  • 兼容Java
  • 编译速度至少同Java一样快
  • 比Java更安全
  • 比Java更简洁
  • 比最成熟的竞争者Scala还简单

与其他JVM上的语言一样,编译成Java字节码

https://www.kotlincn.net/docs/tutorials/ 中文文档

https://kotlinlang.org/docs/reference/comparison-to-java.html 英文文档中对比Java的索引

为什么要使用

非语言层面

  • Jetbrains自己用于开发桌面IDE
  • 谷歌钦定,不用担心跑路没支持
  • 谷歌Demo和很多开源项目开始全面采用,不学看不懂了
  • Android Studio支持完善

语言层面

对下文中提到的Kotlin做出的语言上的改进做一个总结:

  • 通过语法层面的改进规范了一些行为
  • “消灭”了NPE
  • 语法更加灵活清晰/减少冗杂的代码
  • 变量声明更加符合直觉
  • 代码逻辑更加收敛/符合直觉
  • 减少样板代码的使用
  • 更舒服的lambda

最终归在一点:集中精力 提高效率 减少错误

阅读全文 »

写在前面

在汇编课程中的实验中要求了我们在80x86下实现C语言与汇编代码的混合编程,虽然80x86时代离现代有些久远,但我们仍可以把80x86当作x86的一个简化版本来学习一些重要的概念。

从一个例子开始

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
extern int test_fun(void *param);
extern int var_from_asm;
int global_init = 10;
int global;
static int static_init = 1000;
static int static_var;
char *string = "test string";
int main() {
int value = 666;
test_fun(&value);
printf("var from asm:%d\n", var_from_asm);
printf("assign from asm:%d\n", global);
printf("value passed by stack:%d\n", global_init);
return 0;
}
阅读全文 »

写在前面

官方文档关于测试一节中,介绍了测试金字塔这一概念:

即我们应该包括三个层次的测试:小型、中型、与大型:

  • 小型测试是单元测试,即可以独立运行在每个模块上的测试。它们通常模拟了每个主要的组件并且应该快速地运行。
  • 中型测试是介于大型与小型测试之间的综合测试,它们集成了数个组件并且运行在模拟器或实机上。
  • 大型测试是以模拟UI工作流方式进行的综合UI测试,它们保证了关键的终端用户的使用可以符合我们的预期。
    虽然小型测试迅速并且专注,可以让我们很快地发现错误,但它们同样是低仿真且自成一体的,这使得我们很难保证通过了所有的单元测试就可以成功地让App运行。而大型测试的优缺点恰恰与上述相反。
    由于每个层次的测试的角色各不相同,我们应该进行所有这三个层次的测试,尽管各个层次使用比例需要根据App的使用特点,通常建议三个测试的比例为1:2:7。
    UI自动化测试即属于上面说的大型测试。
    阅读全文 »

View触摸事件分发

经过前面的两篇文章,我们终于从内核(触摸事件的真正来源)一路经过Native层通过消息机制来到了需要接收的应用的主线程消息队列中然后被处理,首先调用的是应用根ViewDecorView)的dispatchPointerEvent()方法(继承自View):

1
2
3
4
5
6
7
public final boolean dispatchPointerEvent(MotionEvent event) {
if (event.isTouchEvent()) {
return dispatchTouchEvent(event);
} else {
return dispatchGenericMotionEvent(event);
}
}

调用了ViewGroupdispatchTouchEvent()方法(DecorView继承自FrameLayout):

阅读全文 »

之前的两篇文章讲解了java层消息机制的过程以及使用,中间省略了比较多的代码就是在native层实现的消息机制中使用的。这篇文章就对这一部分进行讲解。

起点

我们从第一篇文章知道,Looper.loop()方法被调用后,会启动一个无限循环,而在这个循环中,调用了MessageQueuenext()方法以获取下一条消息,而next()方法中会首先调用nativePollOnce()方法,这个方法的作用在之前说过是阻塞,达到超时时间或有新的消息到达时得到eventFd的通知再唤醒消息队列,其实这个方法也是native消息处理的开始。

阅读全文 »

Android 消息机制(一)消息队列的创建与循环的开始 Looper与MessageQueue中讲述了消息机制的底层实现,下面就从平时所常用的Handler来讲述消息机制的使用。

Handler

Handler是我们平时进行异步、多线程开发中常用的一个组件,如果在应用主线程中调用阻塞的或者资源消耗量大的任务,会造成UI的更新卡顿,所以我们会将这样的任务放在新的线程中进行操作。当需要通知UI进行更新时,我们会使用Handler创建消息丢入主线程的消息队列,再等待主线程的Handler的处理方法随着消息的处理而被调用,再进行下面的操作。这是Handler的基本用法,它的实现就与消息机制密切相关。

下面我们就对它的实现进行分析。

阅读全文 »

写在前面

本文基于Android 7.1.1 (API 25)的源码分析编写

与之前的触摸事件分发机制分析的文章一样,Android系统机制的分析中关键的一环就是事件消息的处理。之前也说过,Android本质上是一个事件驱动的模型,通过各式各样不断产生事件消息的来推动UI、数据的更新与对我们交互的反馈,没有事件消息的产生,就不会有直观的界面的变化,也就不会有应用丰富的功能。

所以Android的消息机制与其他过程的关系是极其紧密的,例如启动Activity的过程就涉及到ActivityManagerService与应用主进程的通信,产生的通知消息通过Binder机制送入应用主进程的消息队列,再由主进程的消息循环来读取这一消息来进行处理。之前触摸事件分发中也是利用了应用主进程的消息队列来读取我们的触摸事件再进行后续的分发处理。可以说消息队列在各种通信过程中无处不在。

消息队列的存在为异步处理提供了一个非常好的基础,有了消息队列之后,我们就可以在新的线程中处理计算、IO密集、阻塞的任务而不会影响UI的更新,在处理过程中可以通过向消息队列中放入消息来进行UI的更新操作,而发送消息的行为也避免了工作线程为了等待返回而造成的阻塞。

可以说,想要了解其他基于事件的过程,对主线程消息机制的了解是必不可少的基础,在触摸事件分发机制分析的文章中我对消息机制还不是很了解,所以后来发现分析中有很多描述不妥的地方,所以在对消息机制的系统学习之后我又修改完善了这部分的内容。

阅读全文 »