人脸匹配好友列表
MoMo Lv5

概述

内容

人脸匹配好友列表

需求

  1. 算法检测出的人脸配到当前的好友列表
  2. 如果有好友的人脸显示好友名称

过程

设置备注页

Activity

新建一个activity文件用于展示当前点击的头像

layout/activity_user_face.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.userface.UserFaceActivity">

<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_user_name"
android:name="com.danale.edge.ui.userface.UserFaceFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/fragment_user_face" />

</androidx.constraintlayout.widget.ConstraintLayout>

com/danale/edge/ui/userface/UserFaceActivity.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
78
79
80
81
82
83
84
85
86
87
88
package com.danale.edge.ui.userface

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import com.danale.edge.R
import com.danale.edge.base.BaseActivity
import com.danale.edge.base.BaseNavigation.Constants
import com.danale.edge.ui.userface.UserFaceViewModel.Companion.REQUEST_CODE
import com.danale.edge.usersdk.usecase.UserSdkUseCase
import com.google.gson.Gson
import dagger.hilt.android.AndroidEntryPoint
import io.reactivex.rxjava3.kotlin.subscribeBy
import io.reactivex.rxjava3.schedulers.Schedulers
import java.nio.charset.StandardCharsets
import javax.inject.Inject

@AndroidEntryPoint
class UserFaceActivity : BaseActivity() {

private val viewModel: UserFaceViewModel by viewModels()

@Inject
lateinit var userSdk: UserSdkUseCase

@Inject
lateinit var gson: Gson

// 当前点击的人脸下标
private var mainPosition: Int? = 0

companion object {
const val CURRENT_USER_FACE = "CURRENT_USER_FACE"
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user_face)
}

@SuppressLint("CheckResult")
override fun onResume() {
super.onResume()

// 拿到当前用户下标
mainPosition = intent?.getIntExtra(Constants.EXTRA_SEARCH_MAIN_POSITION, 0)
viewModel.loadSearchHistoryItems(mainPosition)

/**
* 加载人脸的好友数据
* */
userSdk.loadAssistData(CURRENT_USER_FACE)
.subscribeOn(Schedulers.io())
.subscribeBy(onSuccess = {
val cb = StandardCharsets.UTF_8.decode(it)
val json = cb.toString()
logger.d(
TAG,
"decode, buffer=${it?.remaining()}, json=${json}"
)
val mapData = gson.fromJson(json, MutableMap::class.java)
val name = mapData[mainPosition.toString()]
viewModel.setName(name as String?)
}, onError = {
logger.w(TAG, "load assist, buffer, error", it)
})
}

/**
* 这里用到了startActivityForResult,用于页面带参数返回,参考
* https://blog.csdn.net/weixin_41008021/article/details/90346700
*/
@Deprecated("Deprecated in Java")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_CODE -> {
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
viewModel.setName(data.getStringExtra(Constants.EXTRA_SEARCH_MAIN_POSITION))
}
}
}
}
}
}

Fragment

layout/fragment_user_face.xml

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
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

<variable
name="viewModel"
type="com.danale.edge.ui.userface.UserFaceViewModel" />

<import type="android.view.View" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/art_bg_flow"
tools:context=".ui.userface.UserFaceActivity">

<com.danale.edge.ui.common.view.TopSafeAreaGuideLine
android:id="@+id/safe_area_top_guide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="24dp"
tools:ignore="MissingConstraints" />

<include
android:id="@+id/component_title_bar"
layout="@layout/component_title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/safe_area_top_guide" />

<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_persons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adapter="@{viewModel.searchPersonAdapter}"
tools:background="#AFBC9D" />

<TextView
android:id="@+id/tv_user_nickname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@{viewModel.currentUserName}"
android:textColor="@color/app_std_text_white"
android:textSize="18sp"
tools:text="Alcidae Username" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_rounded_button"
android:backgroundTint="@color/app_primary"
android:onClick="@{viewModel::onClickSetFriend}"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:text="@string/text_replay"
android:textColor="@color/app_std_text_primary_inverse"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.appcompat.widget.LinearLayoutCompat>

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

com/danale/edge/ui/userface/UserFaceFragment.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
package com.danale.edge.ui.userface

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.get
import androidx.recyclerview.widget.LinearLayoutManager
import com.danale.edge.R
import com.danale.edge.base.BaseFragment
import com.danale.edge.databinding.FragmentUserFaceBinding

class UserFaceFragment : BaseFragment() {
private lateinit var viewModel: UserFaceViewModel
lateinit var binding: FragmentUserFaceBinding

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {

viewModel = ViewModelProvider(requireActivity()).get()
binding =
DataBindingUtil.inflate(inflater, R.layout.fragment_user_face, container, false)
binding.viewModel = this.viewModel
binding.lifecycleOwner = viewLifecycleOwner

binding.recyclerPersons.apply {
layoutManager =
LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
}

viewModel = ViewModelProvider(requireActivity()).get()
binding.viewModel = this.viewModel

return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
observeNavigation(viewModel)
}

override fun onResume() {
super.onResume()
setStatusBarDarkText(false, inverseOnNightMode = false)
}
}

image

ViewModel

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
97
98
99
100
101
102
103
104
package com.danale.edge.ui.userface

import android.annotation.SuppressLint
import android.app.Application
import android.content.Intent
import android.view.View
import androidx.databinding.ObservableField
import androidx.lifecycle.viewModelScope
import com.danale.edge.base.BaseNavigation
import com.danale.edge.base.BaseViewModel
import com.danale.edge.intelligence.IntelligenceRepository
import com.danale.edge.ui.common.adapter.PersonAdapter
import com.danale.edge.ui.common.adapter.ThumbnailAdapter
import com.danale.edge.ui.common.callback.RecyclerItemOnClick
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject


@HiltViewModel
class UserFaceViewModel @Inject constructor(application: Application) : BaseViewModel(application),
RecyclerItemOnClick<ThumbnailAdapter.ThumbnailViewHolder> {

@Inject
lateinit var ai: IntelligenceRepository

// 当前用户名称
var currentUserName = ObservableField("")

private var mainPosition = 0

// 用于给activity传参的标志
companion object {
const val REQUEST_CODE = 1
}


/**
* 当前页面的头像
* */
val searchPersonAdapter =
PersonAdapter(itemOnClick = object : RecyclerItemOnClick<PersonAdapter.PersonViewHolder> {
override fun onClickItem(viewHolder: PersonAdapter.PersonViewHolder) {
logger.d(TAG, "onClickPerson=$viewHolder")
}
})


/**
* 加载当前点击的人脸图片
* */
@SuppressLint("NotifyDataSetChanged")
fun loadSearchHistoryItems(position: Int?) {
if (position != null) {
mainPosition = position
}
viewModelScope.launch {
val faceUsers = withContext(Dispatchers.IO) {
ai.getFaceUserList()
}
searchPersonAdapter.list.clear()
searchPersonAdapter.list.add(faceUsers[position!!])
// fixme: SuppressLint 后续换SortedList
searchPersonAdapter.notifyDataSetChanged()
}
}

/**
* 设置名称
* */
@SuppressLint("NotifyDataSetChanged")
fun setName(name: String?) {
logger.d(TAG, "setName, name = $name")
currentUserName.set(name)
}

/**
* 点击设置名称
* */
@Suppress("UNUSED_PARAMETER") // View.OnClickListener
fun onClickSetFriend(view: View) {
val intent = Intent().apply {
putExtra(
BaseNavigation.Constants.EXTRA_SEARCH_MAIN_POSITION,
mainPosition,
)
}
// BaseNavigation封装的方法
navigationRequiredEvent.postValue(
BaseNavigation(
BaseNavigation.Route.USER_FACE_FRIEND_LIST,
intent,
true,
REQUEST_CODE
)
)
}

override fun onClickItem(viewHolder: ThumbnailAdapter.ThumbnailViewHolder) {
logger.d(TAG, "viewHolder=$viewHolder")
}
}

这里的跳转用到了onActivityResult, 使用的是BaseNavigation封装后的方法,第三个参数为是否开启startForResult,第四个参数是标志

封装的方法如下:

1
2
3
4
5
6
7
8
9
10
fun launch(fromActivity: Activity, intent: Intent? = null) {
val finalIntent = Intent(fromActivity, route.activityClass)
paramIntent?.let { finalIntent.putExtras(it) }
intent?.let { finalIntent.putExtras(it) }
if (startForResult) {
fromActivity.startActivityForResult(finalIntent, requestCode, requestBundle)
} else {
fromActivity.startActivity(finalIntent)
}
}

每次跳转都会走到launch函数中

好友列表页

Activity

com/danale/edge/ui/userface/UserFaceFriendListActivity.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
package com.danale.edge.ui.userface

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import com.danale.edge.R
import com.danale.edge.base.BaseActivity
import com.danale.edge.base.BaseNavigation
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.*

@AndroidEntryPoint
class UserFaceFriendListActivity : BaseActivity() {

private val viewModel: UserFaceFriendListViewModel by viewModels()

@SuppressLint("SuspiciousIndentation")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user_face_friend_list)

// 第一次跳转过来的时候拿到点击的下标
val mainPosition =
intent?.getIntExtra(BaseNavigation.Constants.EXTRA_SEARCH_MAIN_POSITION, 0)
if (mainPosition != null) {
viewModel.setPosition(mainPosition)
}

MainScope().launch {
viewModel.loadPlatformContactList()
}
}

override fun onResume() {
super.onResume()
viewModel.navigationRequiredEvent.observe(this) {
it?.launch(this)
}
observeNavigation(viewModel)

// 非首次跳转
// 监听viewModel的liveData
viewModel.liveData.observe(this) {
val intent = Intent().apply {
putExtra(
BaseNavigation.Constants.EXTRA_SEARCH_MAIN_POSITION,
it,
)
}

// 返回上一页面
setResult(Activity.RESULT_OK, intent)
finish()
}
}
}

跳转的逻辑写在了ViewModel中,无法调用Acitvity中的setResultfinish方法,因此通过一个liveData传值通知Activity进行相关操作,ViewModel与Activity/Fragments通讯的正确姿势 - 掘金 (juejin.cn)

layout/activity_user_face_friend_list.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.userface.UserFaceFriendListActivity">

<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_user_name"
android:name="com.danale.edge.ui.userface.UserFaceFriendListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/fragment_user_face_friend_list" />

</androidx.constraintlayout.widget.ConstraintLayout>

Fragment

layout/fragment_user_face_friend_list.xml

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
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

<variable
name="viewModel"
type="com.danale.edge.ui.userface.UserFaceFriendListViewModel" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/app_std_background_gray">

<com.danale.edge.ui.common.view.TopSafeAreaGuideLine
android:id="@+id/safe_area_top_guide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="24dp"
tools:ignore="MissingConstraints" />

<include
android:id="@+id/component_title_bar"
layout="@layout/component_title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/safe_area_top_guide" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:adapter="@{viewModel.starUserAdapter}"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingBottom="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/component_title_bar" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

com/danale/edge/ui/userface/UserFaceFriendListFragment.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
package com.danale.edge.ui.userface

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.get
import androidx.recyclerview.widget.LinearLayoutManager
import com.danale.edge.R
import com.danale.edge.base.BaseFragment
import com.danale.edge.databinding.FragmentUserFaceFriendListBinding

class UserFaceFriendListFragment : BaseFragment() {

private lateinit var binding: FragmentUserFaceFriendListBinding
private lateinit var viewModel: UserFaceFriendListViewModel

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_user_face_friend_list,
container,
false
)
binding.lifecycleOwner = viewLifecycleOwner

binding.componentTitleBar.apply {
leftIconRes = R.mipmap.ic_back_black
responder = this@UserFaceFriendListFragment
}

binding.recyclerView.apply {
layoutManager =
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
itemAnimator?.changeDuration = 0L // 关闭变化动画防止刷新内容时闪烁
}

viewModel = ViewModelProvider(requireActivity()).get()
binding.viewModel = this.viewModel


return binding.root
}

override fun onResume() {
super.onResume()
setStatusBarDarkText(true)
}

}

image

ViewModel

com/danale/edge/ui/userface/UserFaceFriendListViewModel.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
package com.danale.edge.ui.userface

import android.annotation.SuppressLint
import android.app.Application
import androidx.lifecycle.MutableLiveData
import com.danale.edge.base.BaseViewModel
import com.danale.edge.ui.common.adapter.ThumbnailAdapter
import com.danale.edge.ui.common.callback.RecyclerItemOnClick
import com.danale.edge.ui.common.groupie.UserFaceFriendItem
import com.danale.edge.usersdk.usecase.UserSdkUseCase
import com.google.gson.Gson
import com.xwray.groupie.GroupieAdapter
import com.xwray.groupie.Section
import dagger.hilt.android.lifecycle.HiltViewModel
import io.reactivex.rxjava3.kotlin.subscribeBy
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.rx3.awaitLast
import kotlinx.coroutines.rx3.awaitSingleOrNull
import kotlinx.coroutines.withContext
import org.json.JSONException
import org.json.JSONObject
import java.nio.charset.StandardCharsets
import javax.inject.Inject


@HiltViewModel
class UserFaceFriendListViewModel @Inject constructor(application: Application) :
BaseViewModel(application),
RecyclerItemOnClick<ThumbnailAdapter.ThumbnailViewHolder> {

// 用于加载页面的Adapter
val starUserAdapter = GroupieAdapter()

// 最终列表中的数据格式
data class UserFaceFriend(
var name: String?,
var url: String?,
var nameId: String?
)

// 最终求交集的星标列表
private var userFaceFriendList = ArrayList<UserFaceFriend>()

private var mainPosition = 0

@Inject
lateinit var userSdk: UserSdkUseCase

@Inject
lateinit var gson: Gson

val liveData = MutableLiveData<String>()


companion object {
const val CURRENT_USER_FACE = "CURRENT_USER_FACE"
}

/**
* 拿到对应position
* */
fun setPosition(position: Int) {
mainPosition = position
}


/**
* 加载好友列表
*/
suspend fun loadPlatformContactList(refresh: Boolean = false) {
try {
// 获取的好友列表
withContext(Dispatchers.IO) {
sdk.getFriendsList(forceReFetch = refresh).awaitLast().map {
// 用户名
val displayName = if (it.remarkName?.isNotEmpty() == true) {
it.remarkName
} else {
it.likeName
}

// 用户头像
val url = withContext(Dispatchers.IO) {
it.userName?.let { it1 ->
sdk.getPhotoUrlByPlatformUserName(it1).awaitSingleOrNull()
}
}

// 添加数据
userFaceFriendList.add(
UserFaceFriend(
displayName,
url,
it.userName
)
)
}
}

// 构建列表
buildSettingItems()

} catch (e: Exception) {
toastError(e)
}

}

/**
* 构建好友列表
* */
@SuppressLint("CheckResult")
private fun buildSettingItems() {
logger.d(TAG, "buildSettingItems starFriendList=${userFaceFriendList}")
starUserAdapter.apply {
add(Section().apply {
for ((i, item) in userFaceFriendList.withIndex()) {
item.url?.let { url ->
item.name?.let { name ->
UserFaceFriendItem(
avatar = url, // 头像链接
name = name, // 用户名
clickListener = {
// 加载数据
userSdk.loadAssistData(CURRENT_USER_FACE)
.subscribeOn(Schedulers.io())
.subscribeBy(onSuccess = {
val cb = StandardCharsets.UTF_8.decode(it)
val json = cb.toString()

val mapJson = if (json == "null") {
val data = mapOf("$mainPosition" to name)
gson.toJson(data)
} else {
val mapData = getMap(json)
// 添加数据
mapData?.set(mainPosition.toString(), name)
gson.toJson(mapData)
}

//更新数据
userSdk.storeAssistData(
CURRENT_USER_FACE, mapJson.toByteArray(StandardCharsets.UTF_8)
)
.subscribeOn(Schedulers.io())
.subscribeBy(onSuccess = {
logger.d(TAG, "updateFaceUserList, buffer, success")
}, onError = { e ->
logger.e(TAG, "updateFaceUserList, buffer, error",e)
})
// 传递给liveData通知activity跳转
liveData.postValue(mainPosition.toString())

}, onError = {
logger.w(TAG, "load assist, buffer, error", it)
})
}
)
}
}?.let { add(it) }
}
})
}
}


private fun getMap(jsonString: String?): HashMap<String, Any>? {
val jsonObject: JSONObject
try {
jsonObject = jsonString?.let { JSONObject(it) }!!
val keyIter: Iterator<String> = jsonObject.keys()
var key: String
var value: Any
val valueMap = HashMap<String, Any>()
while (keyIter.hasNext()) {
key = keyIter.next()
value = jsonObject[key] as Any
valueMap[key] = value
}
return valueMap
} catch (e: JSONException) {
e.printStackTrace()
}
return null
}


override fun onClickItem(viewHolder: ThumbnailAdapter.ThumbnailViewHolder) {
logger.d(TAG, "viewHolder=$viewHolder")
}
}

结果

Powered by Hexo & Theme Keep
Unique Visitor Page View