设置页面
MoMo Lv5

概述

内容

设置页面动态生成

需求

  1. 展示的内容完全通过配置确定
  2. 设置项的值目前有开关,数值和枚举三种情况,预留未来扩展
  3. 设置项的描述支持标题和副标题,预留未来扩展
  4. 支持跳转二级页面
  5. 支持分组

预计周期

1~2周

过程

实现数据获取接口

配置接口类型

新建一个operation文件用来定义接口的入参和出参

com/danale/edge/usersdk/operation/GetDeviceSettingListOp.kt

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.danale.edge.usersdk.operation

import com.danale.edge.foundation.log.Logger
import com.danale.edge.usersdk.jni.BaseJsonOperation
import com.danale.edge.usersdk.jni.BaseResponse
import com.google.gson.Gson
import com.google.gson.annotations.SerializedName


class GetDeviceSettingListOp (val param: Param, logger: Logger, gson: Gson) :
BaseJsonOperation<GetDeviceSettingListOp.Response>(logger, gson) {

// 这里是回调
override fun unmarshallSerializedResponse(jsonOutput: String?): Response {
val response = Response()
val array = gson.fromJson(jsonOutput, Array<ResultBean>::class.java)
response.list = array
return response
}

// 传入数据
override fun performOperation(context: CallbackContext) {
context.nativeResponseCallback(0, 0, "", mockList) // 在这里使用mock数据
}

// 入参
class Param(
@SerializedName("device_id") val deviceId: String,
@SerializedName("device_type") val deviceType: Int,
)

// 出参
class Response : BaseResponse() {

// 返回一个Array
var list: Array<ResultBean>? = null

override fun toString(): String {
return "Response(list=${list?.contentToString()})"
}

}

class ResultBean {

@SerializedName("name")
val name: String? = null

@SerializedName("items")
val items: Array<Item>? = null

override fun toString(): String {
return "ResultBean(name=$name, items=$items)"
}

}

class Item {

@SerializedName("id")
val id: String? = null

@SerializedName("type")
val type: String? = null

@SerializedName("subId")
val subId: String? = null

override fun toString(): String {
return "Item(id=$id, type=$type, subId=$subId)"
}

}



}

mock数据如下

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
[
{
"name": "text_basic_setting",
"items": [
{
"id": "text_device_name",
"type": "String"
},
{
"id": "text_device_info",
"type": "Fragment"
},
{
"id": "text_service_net",
"type": "Fragment"
},
{
"id": "Synchronize",
"subId": "SynchronizeDescribe",
"type": "Boolean"
}
]
},
{
"name": "text_device_setting",
"items": [
{
"id": "text_device_flip",
"subId": "flipDescribe",
"type": "Boolean"
}
]
}
]

接口定义和实现

在userSdk中定义接口路径

com/danale/edge/usersdk/usecase/UserSdkUseCase.kt

1
2
3
4
5
6
7
/**
* 获取设备设置列表
*/
fun getDeviceSettingList(
id: String,
type: Int
): Single<GetDeviceSettingListOp.Response>

在userSdkImpl中实现

com/danale/edge/usersdk/usecase/UserSdkUseCaseImpl.kt

1
2
3
4
5
6
override fun getDeviceSettingList(
id: String,
type: Int
): Single<GetDeviceSettingListOp.Response> {
return GetDeviceSettingListOp(GetDeviceSettingListOp.Param(id, type), logger, gsonInst)
}

数据获取

在viewModel中获取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 获取设备设置列表
*/
private fun loadSettingList() {
viewModelScope.launch {
val list = withContext(Dispatchers.IO) {
try {
deviceId32?.let {
logger.d(TAG, "loadSettingList, getDeviceSettingList")
sdk.getDeviceSettingList(it, deviceTypeCode).await()
}

} catch (e: Exception) {
toastError(e)
null
}
}
}
}
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
when (title) {
"text_basic_setting" -> {
add(Section().apply {
setHeader(SectionHeaderItem(getString(R.string.text_setting_basic)))
when (item.id) {
"text_setting_basic_device_name" -> {
add(nameItem)
}
"text_setting_basic_device_info" -> {
add(
StatusItem(
getString(R.string.text_setting_basic_device_info),
actionId = ACTION_NAV_ID_DEVICE_INFO
)
)
}
"text_setting_basic_device_network" -> {
add(
StatusItem(
getString(R.string.text_setting_basic_device_network),
actionId = ACTION_NAV_ID_DEVICE_NETWORK
)
)
}
"Synchronize" -> {
add(
SwitchItem(
getString(R.string.text_allow_metered_sync),
subTitle = getString(R.string.text_allow_metered_sync_tip),
backgroundResId = R.drawable.bg_round_bottom,
showSeparator = false,
loadBlock = { item ->
val useMeteredData =
preference.getAllowMeteredDataCompute()
logger.d(TAG, "load, useMeteredData, $useMeteredData")
(item as? SwitchItem)?.isChecked = useMeteredData
},
checkedListener = { button, isChecked ->
logger.d(
TAG,
"cellular sync change, $isChecked, $button"
)
preference.setAllowMeteredDataCompute(isChecked)
}
))
}
}
})

}
"text_setting_device" -> {
add(Section().apply {
setHeader(SectionHeaderItem(getString(R.string.text_setting_device)))
when (item.id) {
"text_setting_ipc_flip_state" -> {
add(
SwitchItem(
getString(R.string.text_setting_ipc_flip_state),
subTitle = getString(R.string.text_setting_ipc_flip_state_tip),
backgroundResId = R.drawable.bg_round_bottom,
showSeparator = false,
loadBlock = { item ->
logger.d(TAG, "loadBlock, flip, $item")
val state = deviceThingInfo?.run {
performOnIOWithDefault(null) {
sdk.getDeviceFlipStatusWithCache(this).await()
}
} ?: DpFlipState.NORMAL
logger.d(TAG, "loadBlock, flip state, $state")
(item as? SwitchItem)?.isChecked =
(state == DpFlipState.UP_SIDE_DOWN)
},
checkedListener = { button, isChecked ->
logger.d(
TAG,
"checkedListener, flip, $isChecked, $button"
)
val state =
if (isChecked) DpFlipState.UP_SIDE_DOWN else DpFlipState.NORMAL
viewModelScope.launch {
performOnIOWithDefault(null) {
deviceThingInfo?.let {
sdk.setDeviceFlipStatusWithCache(it, state)
.await()
}
}
}
}
))
}

}

})
}
}

image

com/danale/edge/appbiz/ApplicationBusinessModule.kt

1
2
3
4
5
6
7
@Module
@InstallIn(SingletonComponent::class)
interface ApplicationBusinessModule {
@Binds
@Singleton
fun bindSettingItemFactory(impl: SettingItemFactory): SettingItemRepository
}

com/danale/edge/ui/devicecontrol/setting/SettingItemRepository.kt

1
2
3
4
package com.danale.edge.ui.devicecontrol.setting

interface SettingItemRepository {
}

com/danale/edge/ui/devicecontrol/setting/DeviceSettingListViewModel.kt

1
2
3
// 设置项map
@Inject
lateinit var settingItem: SettingItemFactory

com/danale/edge/ui/devicecontrol/setting/SettingItemFactory.kt

1
2
3
4
5
6
7
8
9
10
11
class SettingItemFactory @Inject constructor(
private val preference: AppPrefRepository
) :SettingItemRepository {

fun syncAction(item: BaseSettingItem<RecyclerGroupieItemSwitchBinding>): Boolean {
val useMeteredData = preference.getAllowMeteredDataCompute()
(item as? SwitchItem)?.isChecked = useMeteredData
return useMeteredData
}

}
Powered by Hexo & Theme Keep
Unique Visitor Page View