更新关注逻辑

This commit is contained in:
2024-12-01 15:13:47 +08:00
parent 79fccda1aa
commit c54d5c914a
14 changed files with 199 additions and 156 deletions

View File

@@ -149,8 +149,6 @@ object AppState {
FavouriteNoticeViewModel.ResetModel() FavouriteNoticeViewModel.ResetModel()
// 重置粉丝通知页面 // 重置粉丝通知页面
FollowerNoticeViewModel.ResetModel() FollowerNoticeViewModel.ResetModel()
// 重置关注列表页面
FollowingListViewModel.ResetModel()
// 重置关注通知页面 // 重置关注通知页面
IndexViewModel.ResetModel() IndexViewModel.ResetModel()
UserId = null UserId = null

View File

@@ -349,4 +349,15 @@ class MomentLoader : DataLoader<MomentEntity,MomentLoaderExtraArgs>() {
onListChanged?.invoke(this.list) onListChanged?.invoke(this.list)
} }
fun updateFollowStatus(authorId:Int,isFollow:Boolean) {
this.list = this.list.map { momentItem ->
if (momentItem.authorId == authorId) {
momentItem.copy(followStatus = isFollow)
} else {
momentItem
}
}.toMutableList()
onListChanged?.invoke(this.list)
}
} }

View File

@@ -0,0 +1,6 @@
package com.aiosman.ravenow.event
data class FollowChangeEvent(
val userId: Int,
val isFollow: Boolean
)

View File

@@ -0,0 +1,85 @@
package com.aiosman.ravenow.ui.follower
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.cachedIn
import androidx.paging.map
import com.aiosman.ravenow.data.UserServiceImpl
import com.aiosman.ravenow.entity.AccountPagingSource
import com.aiosman.ravenow.entity.AccountProfileEntity
import com.aiosman.ravenow.event.FollowChangeEvent
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
open class BaseFollowModel:ViewModel() {
private val userService = UserServiceImpl()
private val _usersFlow = MutableStateFlow<PagingData<AccountProfileEntity>>(PagingData.empty())
val usersFlow = _usersFlow.asStateFlow()
var isLoading by mutableStateOf(false)
open var followerId: Int? = null
open var followingId: Int? = null
init {
EventBus.getDefault().register(this)
}
fun loadData(id: Int,force : Boolean = false) {
if (isLoading) return
isLoading = true
viewModelScope.launch {
Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = {
AccountPagingSource(
userService,
followerId = followingId,
followingId = followerId
)
}
).flow.cachedIn(viewModelScope).collectLatest {
_usersFlow.value = it
}
}
isLoading = false
}
@Subscribe
fun onFollowChangeEvent(event: FollowChangeEvent) {
updateIsFollow(event.userId, event.isFollow)
}
private fun updateIsFollow(id: Int, isFollow: Boolean = true) {
val currentPagingData = usersFlow.value
val updatedPagingData = currentPagingData.map { user ->
if (user.id == id) {
user.copy(isFollowing = isFollow)
} else {
user
}
}
_usersFlow.value = updatedPagingData
}
suspend fun followUser(userId: Int) {
userService.followUser(userId.toString())
EventBus.getDefault().post(FollowChangeEvent(userId, true))
}
suspend fun unFollowUser(userId: Int) {
userService.unFollowUser(userId.toString())
EventBus.getDefault().post(FollowChangeEvent(userId, false))
}
override fun onCleared() {
super.onCleared()
EventBus.getDefault().unregister(this)
}
}

View File

@@ -17,9 +17,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import com.aiosman.ravenow.LocalAppTheme import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.exp.viewModelFactory
import com.aiosman.ravenow.ui.comment.NoticeScreenHeader import com.aiosman.ravenow.ui.comment.NoticeScreenHeader
import com.aiosman.ravenow.ui.composables.StatusBarMaskLayout import com.aiosman.ravenow.ui.composables.StatusBarMaskLayout
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -27,8 +29,10 @@ import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class) @OptIn(ExperimentalMaterialApi::class)
@Composable @Composable
fun FollowerListScreen(userId: Int) { fun FollowerListScreen(userId: Int) {
val AppColors = LocalAppTheme.current val appColors = LocalAppTheme.current
val model = FollowerListViewModel val model: FollowerListViewModel = viewModel(factory = viewModelFactory {
FollowerListViewModel(userId)
}, key = "viewModel_${userId}")
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val refreshState = rememberPullRefreshState(model.isLoading, onRefresh = { val refreshState = rememberPullRefreshState(model.isLoading, onRefresh = {
model.loadData(userId, true) model.loadData(userId, true)
@@ -38,9 +42,8 @@ fun FollowerListScreen(userId: Int) {
} }
StatusBarMaskLayout( StatusBarMaskLayout(
modifier = Modifier modifier = Modifier
.background(color = AppColors.background) .background(color = appColors.background)
.padding(horizontal = 16.dp), .padding(horizontal = 16.dp),
maskBoxBackgroundColor = AppColors.background,
) { ) {
var dataFlow = model.usersFlow var dataFlow = model.usersFlow
var users = dataFlow.collectAsLazyPagingItems() var users = dataFlow.collectAsLazyPagingItems()

View File

@@ -1,71 +1,7 @@
package com.aiosman.ravenow.ui.follower package com.aiosman.ravenow.ui.follower
import androidx.compose.runtime.getValue class FollowerListViewModel(
import androidx.compose.runtime.mutableStateOf val userId: Int
import androidx.compose.runtime.setValue ) : BaseFollowModel() {
import androidx.lifecycle.ViewModel override var followingId: Int? = userId
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.cachedIn
import androidx.paging.map
import com.aiosman.ravenow.data.UserServiceImpl
import com.aiosman.ravenow.entity.AccountPagingSource
import com.aiosman.ravenow.entity.AccountProfileEntity
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
object FollowerListViewModel : ViewModel() {
private val userService = UserServiceImpl()
private val _usersFlow = MutableStateFlow<PagingData<AccountProfileEntity>>(PagingData.empty())
val usersFlow = _usersFlow.asStateFlow()
private var userId by mutableStateOf<Int?>(null)
var isLoading by mutableStateOf(false)
fun loadData(id: Int,force : Boolean = false) {
if (userId == id && !force) {
return
}
isLoading = true
userId = id
viewModelScope.launch {
Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = {
AccountPagingSource(
userService,
followerId = id
)
}
).flow.cachedIn(viewModelScope).collectLatest {
_usersFlow.value = it
}
}
isLoading = false
}
private fun updateIsFollow(id: Int, isFollow: Boolean = true) {
val currentPagingData = usersFlow.value
val updatedPagingData = currentPagingData.map { user ->
if (user.id == id) {
user.copy(isFollowing = isFollow)
} else {
user
}
}
_usersFlow.value = updatedPagingData
}
suspend fun followUser(userId: Int) {
userService.followUser(userId.toString())
updateIsFollow(userId)
}
suspend fun unFollowUser(userId: Int) {
userService.unFollowUser(userId.toString())
updateIsFollow(userId, false)
}
} }

View File

@@ -34,6 +34,7 @@ import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.NavigationRoute import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.comment.NoticeScreenHeader import com.aiosman.ravenow.ui.comment.NoticeScreenHeader
import com.aiosman.ravenow.ui.composables.CustomAsyncImage import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.FollowButton
import com.aiosman.ravenow.ui.composables.StatusBarMaskLayout import com.aiosman.ravenow.ui.composables.StatusBarMaskLayout
import com.aiosman.ravenow.ui.modifiers.noRippleClickable import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -163,6 +164,13 @@ fun FollowItem(
) { ) {
Text(nickname, fontWeight = FontWeight.Bold, fontSize = 16.sp, color = AppColors.text) Text(nickname, fontWeight = FontWeight.Bold, fontSize = 16.sp, color = AppColors.text)
} }
if (!isFollowing && userId != AppState.UserId) {
FollowButton(
isFollowing = false,
) {
onFollow()
}
}
} }
} }
} }

View File

@@ -16,10 +16,13 @@ import com.aiosman.ravenow.data.UserServiceImpl
import com.aiosman.ravenow.data.UserService import com.aiosman.ravenow.data.UserService
import com.aiosman.ravenow.data.api.ApiClient import com.aiosman.ravenow.data.api.ApiClient
import com.aiosman.ravenow.data.api.UpdateNoticeRequestBody import com.aiosman.ravenow.data.api.UpdateNoticeRequestBody
import com.aiosman.ravenow.event.FollowChangeEvent
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
/** /**
* 关注消息列表的 ViewModel * 关注消息列表的 ViewModel
@@ -32,6 +35,10 @@ object FollowerNoticeViewModel : ViewModel() {
val followerItemsFlow = _followerItemsFlow.asStateFlow() val followerItemsFlow = _followerItemsFlow.asStateFlow()
var isFirstLoad = true var isFirstLoad = true
init {
EventBus.getDefault().register(this)
}
fun reload(force: Boolean = false) { fun reload(force: Boolean = false) {
if (!isFirstLoad && !force) { if (!isFirstLoad && !force) {
return return
@@ -50,12 +57,15 @@ object FollowerNoticeViewModel : ViewModel() {
} }
} }
} }
@Subscribe
private fun updateIsFollow(id: Int) { fun onFollowChangeEvent(event: FollowChangeEvent) {
updateIsFollow(event.userId, event.isFollow)
}
private fun updateIsFollow(id: Int, isFollow: Boolean = true) {
val currentPagingData = _followerItemsFlow.value val currentPagingData = _followerItemsFlow.value
val updatedPagingData = currentPagingData.map { follow -> val updatedPagingData = currentPagingData.map { follow ->
if (follow.userId == id) { if (follow.userId == id) {
follow.copy(isFollowing = true) follow.copy(isFollowing = isFollow)
} else { } else {
follow follow
} }
@@ -64,7 +74,7 @@ object FollowerNoticeViewModel : ViewModel() {
} }
suspend fun followUser(userId: Int) { suspend fun followUser(userId: Int) {
userService.followUser(userId.toString()) userService.followUser(userId.toString())
updateIsFollow(userId) EventBus.getDefault().post(FollowChangeEvent(userId, true))
} }
suspend fun updateNotice() { suspend fun updateNotice() {
@@ -78,4 +88,9 @@ object FollowerNoticeViewModel : ViewModel() {
fun ResetModel() { fun ResetModel() {
isFirstLoad = true isFirstLoad = true
} }
override fun onCleared() {
super.onCleared()
EventBus.getDefault().unregister(this)
}
} }

View File

@@ -24,9 +24,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import com.aiosman.ravenow.LocalAppTheme import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.exp.viewModelFactory
import com.aiosman.ravenow.ui.comment.NoticeScreenHeader import com.aiosman.ravenow.ui.comment.NoticeScreenHeader
import com.aiosman.ravenow.ui.composables.StatusBarMaskLayout import com.aiosman.ravenow.ui.composables.StatusBarMaskLayout
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -34,8 +36,10 @@ import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class) @OptIn(ExperimentalMaterialApi::class)
@Composable @Composable
fun FollowingListScreen(userId: Int) { fun FollowingListScreen(userId: Int) {
val AppColors = LocalAppTheme.current val appColors = LocalAppTheme.current
val model = FollowingListViewModel val model : FollowingListViewModel = viewModel(factory = viewModelFactory {
FollowingListViewModel(userId)
}, key = "viewModel_${userId}")
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val refreshState = rememberPullRefreshState(model.isLoading, onRefresh = { val refreshState = rememberPullRefreshState(model.isLoading, onRefresh = {
model.loadData(userId, true) model.loadData(userId, true)
@@ -45,9 +49,8 @@ fun FollowingListScreen(userId: Int) {
} }
StatusBarMaskLayout( StatusBarMaskLayout(
modifier = Modifier modifier = Modifier
.background(color = AppColors.background) .background(color = appColors.background)
.padding(horizontal = 16.dp), .padding(horizontal = 16.dp),
maskBoxBackgroundColor = AppColors.background
) { ) {
var dataFlow = model.usersFlow var dataFlow = model.usersFlow
var users = dataFlow.collectAsLazyPagingItems() var users = dataFlow.collectAsLazyPagingItems()
@@ -76,14 +79,14 @@ fun FollowingListScreen(userId: Int) {
Spacer(modifier = Modifier.size(32.dp)) Spacer(modifier = Modifier.size(32.dp))
androidx.compose.material.Text( androidx.compose.material.Text(
text = "You haven't followed anyone yet", text = "You haven't followed anyone yet",
color = AppColors.text, color = appColors.text,
fontSize = 16.sp, fontSize = 16.sp,
fontWeight = FontWeight.W600 fontWeight = FontWeight.W600
) )
Spacer(modifier = Modifier.size(16.dp)) Spacer(modifier = Modifier.size(16.dp))
androidx.compose.material.Text( androidx.compose.material.Text(
text = "Click start your social journey.", text = "Click start your social journey.",
color = AppColors.text, color = appColors.text,
fontSize = 16.sp, fontSize = 16.sp,
fontWeight = FontWeight.W400 fontWeight = FontWeight.W400
) )
@@ -109,7 +112,7 @@ fun FollowingListScreen(userId: Int) {
) { ) {
scope.launch { scope.launch {
if (user.isFollowing) { if (user.isFollowing) {
model.unfollowUser(user.id) model.unFollowUser(user.id)
} else { } else {
model.followUser(user.id) model.followUser(user.id)
} }

View File

@@ -18,58 +18,8 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
object FollowingListViewModel : ViewModel() { class FollowingListViewModel(
private val userService = UserServiceImpl() val userId: Int
private val _usersFlow = MutableStateFlow<PagingData<AccountProfileEntity>>(PagingData.empty()) ) : BaseFollowModel() {
var isLoading by mutableStateOf(false) override var followerId: Int? = userId
val usersFlow = _usersFlow.asStateFlow()
private var userId by mutableStateOf<Int?>(null)
fun loadData(id: Int, force: Boolean = false) {
if (userId == id && !force) {
return
}
isLoading = true
userId = id
viewModelScope.launch {
Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = {
AccountPagingSource(
userService,
followingId = id
)
}
).flow.cachedIn(viewModelScope).collectLatest {
_usersFlow.value = it
}
}
isLoading = false
}
private fun updateIsFollow(id: Int, isFollow: Boolean = true) {
val currentPagingData = usersFlow.value
val updatedPagingData = currentPagingData.map { user ->
if (user.id == id) {
user.copy(isFollowing = isFollow)
} else {
user
}
}
_usersFlow.value = updatedPagingData
}
suspend fun followUser(userId: Int) {
userService.followUser(userId.toString())
updateIsFollow(userId)
}
suspend fun unfollowUser(userId: Int) {
userService.unFollowUser(userId.toString())
updateIsFollow(userId, false)
}
fun ResetModel() {
userId = null
}
} }

View File

@@ -11,6 +11,7 @@ import com.aiosman.ravenow.entity.MomentEntity
import com.aiosman.ravenow.entity.MomentLoader import com.aiosman.ravenow.entity.MomentLoader
import com.aiosman.ravenow.entity.MomentLoaderExtraArgs import com.aiosman.ravenow.entity.MomentLoaderExtraArgs
import com.aiosman.ravenow.entity.MomentServiceImpl import com.aiosman.ravenow.entity.MomentServiceImpl
import com.aiosman.ravenow.event.FollowChangeEvent
import com.aiosman.ravenow.event.MomentAddEvent import com.aiosman.ravenow.event.MomentAddEvent
import com.aiosman.ravenow.event.MomentFavouriteChangeEvent import com.aiosman.ravenow.event.MomentFavouriteChangeEvent
import com.aiosman.ravenow.event.MomentLikeChangeEvent import com.aiosman.ravenow.event.MomentLikeChangeEvent
@@ -101,20 +102,26 @@ open class BaseMomentModel :ViewModel(){
momentLoader.addMoment(event.moment) momentLoader.addMoment(event.moment)
} }
@Subscribe
fun onFollowChangeEvent(event: FollowChangeEvent) {
momentLoader.updateFollowStatus(event.userId, event.isFollow)
}
fun followAction(moment: MomentEntity) { fun followAction(moment: MomentEntity) {
// viewModelScope.launch { viewModelScope.launch {
// try { try {
// if (moment.followStatus) { if (moment.followStatus) {
// userService.unFollowUser(moment.authorId.toString()) userService.unFollowUser(moment.authorId.toString())
// } else { EventBus.getDefault().post(FollowChangeEvent(moment.authorId, false))
// userService.followUser(moment.authorId.toString()) } else {
// } userService.followUser(moment.authorId.toString())
// updateFollowStatus(moment.authorId, !moment.followStatus) EventBus.getDefault().post(FollowChangeEvent(moment.authorId, true))
// } catch (e: Exception) { }
// e.printStackTrace() } catch (e: Exception) {
// } e.printStackTrace()
// } }
}
} }
fun ResetModel() { fun ResetModel() {

View File

@@ -95,7 +95,8 @@ fun ExploreMomentsList() {
}, },
onFollowClick = { onFollowClick = {
model.followAction(momentItem) model.followAction(momentItem)
} },
showFollowButton = true
) )
} }
} }

View File

@@ -20,6 +20,7 @@ import com.aiosman.ravenow.entity.MomentEntity
import com.aiosman.ravenow.entity.MomentLoader import com.aiosman.ravenow.entity.MomentLoader
import com.aiosman.ravenow.entity.MomentLoaderExtraArgs import com.aiosman.ravenow.entity.MomentLoaderExtraArgs
import com.aiosman.ravenow.entity.MomentServiceImpl import com.aiosman.ravenow.entity.MomentServiceImpl
import com.aiosman.ravenow.event.FollowChangeEvent
import com.aiosman.ravenow.event.MomentAddEvent import com.aiosman.ravenow.event.MomentAddEvent
import com.aiosman.ravenow.event.MomentFavouriteChangeEvent import com.aiosman.ravenow.event.MomentFavouriteChangeEvent
import com.aiosman.ravenow.event.MomentLikeChangeEvent import com.aiosman.ravenow.event.MomentLikeChangeEvent
@@ -184,4 +185,8 @@ object MyProfileViewModel : ViewModel() {
momentLoader.removeMoment(event.postId) momentLoader.removeMoment(event.postId)
} }
@Subscribe
fun onFollowChangeEvent(event: FollowChangeEvent) {
momentLoader.updateFollowStatus(event.userId, event.isFollow)
}
} }

View File

@@ -12,7 +12,10 @@ import com.aiosman.ravenow.entity.AccountProfileEntity
import com.aiosman.ravenow.entity.MomentEntity import com.aiosman.ravenow.entity.MomentEntity
import com.aiosman.ravenow.entity.MomentLoader import com.aiosman.ravenow.entity.MomentLoader
import com.aiosman.ravenow.entity.MomentLoaderExtraArgs import com.aiosman.ravenow.entity.MomentLoaderExtraArgs
import com.aiosman.ravenow.event.FollowChangeEvent
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
class AccountProfileViewModel : ViewModel() { class AccountProfileViewModel : ViewModel() {
@@ -27,6 +30,9 @@ class AccountProfileViewModel : ViewModel() {
} }
} }
var moments by mutableStateOf<List<MomentEntity>>(listOf()) var moments by mutableStateOf<List<MomentEntity>>(listOf())
init {
EventBus.getDefault().register(this)
}
fun loadProfile(id: String, pullRefresh: Boolean = false) { fun loadProfile(id: String, pullRefresh: Boolean = false) {
viewModelScope.launch { viewModelScope.launch {
@@ -47,19 +53,23 @@ class AccountProfileViewModel : ViewModel() {
} }
} }
} }
@Subscribe
fun onFollowChangeEvent(event: FollowChangeEvent) {
if (event.userId == profile?.id) {
profile = profile?.copy(followerCount = profile!!.followerCount + if (event.isFollow) 1 else -1, isFollowing = event.isFollow)
}
}
fun followUser(userId: String) { fun followUser(userId: String) {
viewModelScope.launch { viewModelScope.launch {
userService.followUser(userId) userService.followUser(userId)
profile = profile?.copy(followerCount = profile!!.followerCount + 1, isFollowing = true) EventBus.getDefault().post(FollowChangeEvent(userId.toInt(), true))
} }
} }
fun unFollowUser(userId: String) { fun unFollowUser(userId: String) {
viewModelScope.launch { viewModelScope.launch {
userService.unFollowUser(userId) userService.unFollowUser(userId)
profile = EventBus.getDefault().post(FollowChangeEvent(userId.toInt(), false))
profile?.copy(followerCount = profile!!.followerCount - 1, isFollowing = false)
} }
} }
@@ -67,4 +77,9 @@ class AccountProfileViewModel : ViewModel() {
val nickName get() = profile?.nickName ?: "" val nickName get() = profile?.nickName ?: ""
val avatar get() = profile?.avatar val avatar get() = profile?.avatar
override fun onCleared() {
super.onCleared()
EventBus.getDefault().unregister(this)
}
} }