我对“状态”与“事件”的理解

最近在业务开发中,对“状态”和“事件”两个概念有些思考,在这里记录一下。

从LiveData的“问题”说起

在 androidx 的 LiveData 和 ViewModel 库刚推出的时候,我也在业务中接入使用,并有了一些思考,可参见之前的文章

阅读全文

在 Android 中使用 Render Node 加速渲染

在刚开始安卓开发的时候,前辈教导我:如果视图渲染出现了什么问题,就把硬件加速关掉。这确实让我绕开了不少显示上的问题。在后面的需求开发中,正好碰到了一个功能点:需要使用一个图片作为蒙层(称为蒙层图片),实际图片(称为内容图片)需要只在蒙层图片有不透明像素的地方显示,以实现对图片的特殊裁剪效果。

阅读全文

使用协程组合管理业务逻辑

在我们的项目中,已经开始推广协程的使用了,其本身的特性让我们在编写并发、异步、后台逻辑时,获得了比其他如 bolt.Tasks 等第三方库更好的开发体验。
在此我将总结一些在业务场景中使用协程的经验。

一个协程框架下的功能怎么写

在使用协程编写业务逻辑之前,我们在耗时任务上使用的三方库、组件API、甚至于说编程思想都是基于回调的概念的:我们从在调用时发起一个异步任务,为其注册好监听事件,随机调用函数返回但没有结果。

阅读全文

RecyclerView 中为 ItemDecoration 应用动画

RecyclerView 中,使用 ItemDecoration 来添加分割线或者侧边装饰条是十分常用的操作,可以实现分割线、装饰条的实现与列表元素解耦,和跨列表元素之间的装饰交互。

但是, ItemDecoration 的画面显示实现是需要开发者自己覆盖 onDraw 方法,在卡片之外自行将画面元素绘制上去。因其绘制过程与卡片本身没有关系,可以想象到的是,卡片在动画过程中不会自动地影响到 ItemDecoration 中所绘制的元素,需要开发者进行额外的适配工作。

阅读全文

RecyclerView 的 item 在动画过程中的点击事件

在项目中应用了 MVVM 模式之后,就能享受到 DiffUtil 带来的计算最小变动集的便利性,以及在列表项更新时能用上自带动画。

但是因为页面更新应用了动画,使得页面响应点击时出现了问题。

问题现象

在我的页面中,列表每一项都带有一个订阅按钮,对应数据有一个 “是否已经订阅” 的字段。每次点击按钮时,都根据目前数据是否已经订阅,向服务器发送订阅或者取消订阅的请求,然后根据请求的返回结果是否成功,使用 DiffUtil 更新当前页面列表项。

阅读全文

Android xml 中 drawable、color 的混用与 selector

平时在安卓项目中需要编写 xml 布局时,我都习惯需要接收 drawable 资源的属性中( 如 android:background )可以按需传入 drawable 资源 ( 如 @drawable/layout_bg ) 和 color 资源 ( 如 @color/layout_bg_color),并且默认在 xml 资源中 color 资源是可以代替 drawable 使用的。

阅读全文

kotlin 中传入形参、返回不匹配的 lambda 表达式

公司的项目里已经大范围应用上了 kotlin ,其 lambda 函数以及高阶函数的特性让我们在开发中享受了不少便利。

最近在 lambda 的使用上遇到了一点小问题,借此稍微探究了一下 kotlin 中 lambda 的小细节,并做一个记录。

起因

在我的代码中,经常需要遍历处理一个 list ,并且将经过处理的数据添加到另一个 list 中,示例如下:

阅读全文

Android 项目中使用 MVVM 模式的一些思考

目前在维护的项目中,有很多页面的代码比较久远,将网络请求、数据处理、页面布局等代码都写在一个 Fragment 中。在项目前期需求比较简单的时候,这样确实能快速开发页面完成需求,但在后面维护的过程中则带来了不便。后来有重构这些页面的机会,在此记录一下实际遇到的问题,以及自己的思考过程。

在我的项目中,页面通常是一个数据列表,通过网络加载数据,然后在页面上显示多个种类的卡片;页面的业务可能需要根据需要对返回数据进行预处理,或者为不同块的数据卡片加上头、尾;同时需要响应用户交互,实时更新数据并且将更新后的数据同步给服务器。

阅读全文

java 构造方法的重载

在安卓项目中经常有需要自定义 View 控件的场景。最近发现了两种声明构造方法的风格:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class View1 extends View {
public View1(Context context) {
this(context, null);
}

public View1(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public View1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, 0);
init();
}

private void init() {
//do some init works
}
}

class View2 extends View {
public View1(Context context) {
super(context);
init();
}

public View1(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}

public View1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, 0);
init();
}

private void init() {
//do some init works
}
}

阅读全文

Android 使用Powermock的单元测试的 Rule 顺序

在使用 Powermock 进行安卓的单元测试的编写时,出现了一些已经被调用了初始化的业务代码在执行测试时没有被初始化的情况,在此记录一下解决问题的过程。

初始项目

首先建立一个类 InitData ,代表需要被初始化的业务单例代码:

阅读全文