Skip to content

Commit d347379

Browse files
committed
update doc
1 parent 35e197c commit d347379

File tree

7 files changed

+46
-40
lines changed

7 files changed

+46
-40
lines changed

README_CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
- 使用状态机实现
1313
- 支持嵌套滑动
14-
- 支持Jetpack compose
14+
- 支持Jetpack Compose
1515
- 易于扩展
1616

1717

doc/statemachine_cn.md

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# 状态机(StateMachine)在下拉刷新控件库中的使用
2-
3-
文中提到的状态机均为有限状态机(FSM)
1+
# 状态机(StateMachine)在下拉刷新控件中的使用
42

53
### 背景
64

5+
在维护下拉刷新控件的过程中,虽然改动的次数很少,但是每一次bug修复和新增功能都很困难,总结问题如下:
6+
77
- 状态转换,状态判断逻辑复杂
88

99
代码中定义了4个下拉刷新的状态以及可以影响刷新状态的其他变量,在手势事件,嵌套滑动,自动刷新等事件的输入情况下,需要对几个变量进行正确判断,再做出响应。
@@ -62,7 +62,7 @@ private fun tryScrollBackToTopAbortRefresh() {
6262
并且让代码简洁,可维护性高?
6363

6464
在思考这个问题的时候,我就想到游戏开发,他们如何在多个玩家进行大量的位移,技能释放等多种事件输入的场景下来保证逻辑正常运转的。如果只是靠简单的if,else判断,那对维护者来说,绝对是个灾难。
65-
随即,我看到了游戏开发中对状态机使用的一些文章。觉得状态机同样适用在下拉刷新库中
65+
随即,我看到了游戏开发中对状态机使用的一些文章。觉得状态机同样适用在下拉刷新控件中
6666

6767
### 什么是状态机
6868

@@ -72,7 +72,7 @@ private fun tryScrollBackToTopAbortRefresh() {
7272

7373
简单的理解,状态机的作用就是,给定一个当前状态和触发事件,状态机能够输出下一个状态。
7474

75-
在软件工程中,状态机有以下几个重要的概念
75+
状态机的几个概念
7676

7777
- 状态(State):表示对象的某种形态,在当前形态下可能会拥有不同的行为和属性。
7878
- 转移(Transition):表示状态变更,并且必须满足确使转移发生的条件来执行。
@@ -118,11 +118,11 @@ sealed class Event {
118118
```kotlin
119119
sealed class SideEffect {
120120
// 手势取消回到顶部
121-
object OnCancelToIdle : SideEffect()
121+
object OnReleaseToIdle : SideEffect()
122122
// 刷新动作
123123
object OnRefreshing : SideEffect()
124124
// 开始拖动控件
125-
object OnDragBegin : SideEffect()
125+
object OnPull : SideEffect()
126126
// 刷新完成的动作
127127
object OnComplete : SideEffect()
128128
}
@@ -172,24 +172,24 @@ var stateMachine =
172172

173173
1. 现在的由于状态转换的触发逻辑,都在`onTransition`的lambda中统一处理,简单易懂
174174

175-
```
176-
when (validTransition.sideEffect) {
177-
SideEffect.OnDragBegin -> { }
178-
SideEffect.OnComplete -> {
179-
// 执行刷新完成的总做
180-
}
181-
SideEffect.OnRefreshing -> {
182-
// 执行刷新动作
183-
}
184-
SideEffect.OnCancelToIdle -> {
185-
// 执行回到顶部的动作
186-
}
187-
}
188-
```
175+
```kotlin
176+
when (validTransition.sideEffect) {
177+
SideEffect.OnDragBegin -> { }
178+
SideEffect.OnComplete -> {
179+
// 执行刷新完成的总做
180+
}
181+
SideEffect.OnRefreshing -> {
182+
// 执行刷新动作
183+
}
184+
SideEffect.OnCancelToIdle -> {
185+
// 执行回到顶部的动作
186+
}
187+
}
188+
```
189189

190190
2. 通过Event触发状态的转换,触发事件时不需要对状态进行判断,因为状态转换的判断都已经在状态机的内部完成
191191

192-
```
192+
```kotlin
193193
// 触发下拉事件
194194
stateMachine.transition(Event.Pull)
195195
...
@@ -202,18 +202,21 @@ var stateMachine =
202202
// 触发自动刷新的事件
203203
stateMachine.transition(Event.AutoRefresh)
204204

205-
```
205+
```
206206

207207
2. 代码逻辑更加简练了,可维护性变好
208208

209209
状态转换的逻辑基本与手势事件,嵌套滑动等其他的逻辑解耦,debug变简单了
210210

211211
### 结论
212212

213-
引入状态机后,抽象程度提高,代码逻辑变简洁。和原来相比更容易阅读和维护了。
213+
引入状态机后,状态的转移流程清晰易懂,代码逻辑变简洁。和原来相比更容易阅读和维护了。
214214

215215

216216
##### 参考
217-
1. [有限状态机](https://zh.wikipedia.org/wiki/%E6%9C%89%E9%99%90%E7%8A%B6%E6%80%81%E6%9C%BA)
218-
2. [趣说游戏AI开发:对状态机的褒扬和批判](https://zhuanlan.zhihu.com/p/20476688)
219-
3. [Unity 教程 | 状态机 1](https://www.bilibili.com/video/BV1St4y1Y7U1)
217+
218+
[有限状态机](https://zh.wikipedia.org/wiki/%E6%9C%89%E9%99%90%E7%8A%B6%E6%80%81%E6%9C%BA)
219+
220+
[趣说游戏AI开发:对状态机的褒扬和批判](https://zhuanlan.zhihu.com/p/20476688)
221+
222+
[Unity 教程 | 状态机 1](https://www.bilibili.com/video/BV1St4y1Y7U1)

ptr-demo/src/main/java/wtf/s1/android/ptr/demo/InsCompose.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ fun Ins() {
3939
NSPtrState(
4040
coroutineScope = coroutine,
4141
contentInitPosition = 0.dp,
42-
contentRefreshPosition = 54.dp
42+
contentRefreshPosition = 60.dp
4343
) {
4444
delay(3000)
4545
it.dispatchPtrEvent(Event.RefreshComplete)
@@ -51,7 +51,7 @@ fun Ins() {
5151
) {
5252
NSPtrEZHeader(
5353
modifier = Modifier
54-
.offset(0.dp, 12.dp),
54+
.offset(0.dp, 16.dp),
5555
nsPtrState = nsPtrState
5656
)
5757
SimpleListCompose(Modifier.ptrContent())

ptr-demo/src/main/java/wtf/s1/android/ptr/demo/SimpleItemView.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package wtf.s1.android.ptr.demo
22

33
import android.content.Context
44
import android.content.Intent
5+
import android.graphics.Color
56
import android.util.AttributeSet
67
import android.view.ViewGroup
78
import android.widget.FrameLayout
@@ -28,6 +29,7 @@ class SimpleItemView @JvmOverloads constructor(
2829

2930
context.startActivity(intent)
3031
}
32+
mTextView.setTextColor(Color.BLACK)
3133
}
3234

3335
fun bind(post: Post) {

ptr-demo/src/main/res/layout/fragment_text.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,21 @@
1212
android:layout_width="match_parent"
1313
android:layout_height="match_parent"
1414
android:fillViewport="true">
15+
1516
<TextView
1617
android:id="@+id/wiki"
17-
android:padding="8dp"
1818
android:layout_width="match_parent"
1919
android:layout_height="wrap_content"
2020
android:background="@android:color/white"
2121
android:gravity="center"
22-
android:scrollbars = "vertical"
22+
android:padding="8dp"
23+
android:scrollbars="vertical"
2324
android:text="@string/dotawiki"
25+
android:textColor="@android:color/black"
2426
android:textSize="16sp" />
2527

2628
</androidx.core.widget.NestedScrollView>
2729

2830

29-
3031
</wtf.s1.android.ptr.demo.SwipeToRefreshLayout>
3132
</merge>

ptr-view/src/main/java/wtf/s1/ptr/nsptr/view/NSPtrEZHeader.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import wtf.s1.ptr.nsptr.State
1010
import wtf.s1.ptr.nsptr.StateMachine
1111

1212
/**
13-
* implement NSPtrHeader in easy way
13+
* implement NSPtrHeader in an easy way
1414
*/
1515
open class NSPtrEZHeader @JvmOverloads constructor(
1616
context: Context, attrs: AttributeSet? = null
@@ -43,12 +43,12 @@ open class NSPtrEZHeader @JvmOverloads constructor(
4343
}
4444
}
4545

46-
override fun onPositionChange(frame: NSPtrLayout, offset: Int) {
47-
if (frame.currentState != State.REFRESHING) {
48-
if (mIsOverToRefresh != frame.isOverToRefreshPosition) {
49-
mIsOverToRefresh = frame.isOverToRefreshPosition
46+
override fun onPositionChange(ptrLayout: NSPtrLayout, offset: Int) {
47+
if (ptrLayout.currentState != State.REFRESHING) {
48+
if (mIsOverToRefresh != ptrLayout.isOverToRefreshPosition) {
49+
mIsOverToRefresh = ptrLayout.isOverToRefreshPosition
5050
}
51-
progressBar.progress = (frame.contentTopPosition * 100f / frame.config.contentRefreshPosition()).toInt()
51+
progressBar.progress = (ptrLayout.contentTopPosition * 100f / ptrLayout.config.contentRefreshPosition()).toInt()
5252
}
5353
}
5454

ptr-view/src/main/java/wtf/s1/ptr/nsptr/view/NSPtrEZLayout.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import android.content.Context
44
import android.util.AttributeSet
55

66
/**
7-
* implement NSPtrEZLayout in easy way
7+
* implement NSPtrEZLayout in an easy way
88
*/
99
open class NSPtrEZLayout @JvmOverloads constructor(
1010
context: Context, attrs: AttributeSet? = null

0 commit comments

Comments
 (0)