Skip to content

Commit

Permalink
增加接口缓存
Browse files Browse the repository at this point in the history
  • Loading branch information
wangchenyan committed Jan 4, 2024
1 parent f1eaf7a commit bf6f73e
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 27 deletions.
3 changes: 3 additions & 0 deletions app/src/main/java/me/wcy/music/MusicApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class MusicApplication : Application() {
textColorBlack = { R.color.common_text_h1_color }
isTitleCenter = false
}
imageLoaderConfig {
placeholderAvatar = R.drawable.ic_launcher_round
}
apiConfig({}) {
codeJsonNames = listOf("code")
msgJsonNames = listOf("message", "msg")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import android.app.Activity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.withContext
import top.wangchenyan.common.ext.showConfirmDialog
import top.wangchenyan.common.ext.toUnMutable
import top.wangchenyan.common.model.CommonResult
import me.wcy.music.account.AccountApi
import me.wcy.music.account.AccountPreference
import me.wcy.music.account.bean.ProfileData
import me.wcy.music.consts.RoutePath
import me.wcy.music.net.NetCache
import me.wcy.router.CRouter
import top.wangchenyan.common.ext.showConfirmDialog
import top.wangchenyan.common.ext.toUnMutable
import top.wangchenyan.common.model.CommonResult
import javax.inject.Inject
import javax.inject.Singleton

Expand Down Expand Up @@ -63,6 +64,7 @@ class UserServiceImpl @Inject constructor() : UserService {
override suspend fun logout() {
withContext(Dispatchers.IO) {
AccountPreference.clear()
NetCache.userCache.clear()
}
_profile.value = null
}
Expand Down
14 changes: 10 additions & 4 deletions app/src/main/java/me/wcy/music/common/ApiDomainDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import android.content.Context
import androidx.core.text.buildSpannedString
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.RegexUtils
import kotlinx.coroutines.launch
import me.wcy.music.R
import me.wcy.music.account.AccountPreference
import me.wcy.music.databinding.DialogApiDomainBinding
import me.wcy.music.net.NetCache
import me.wcy.music.storage.preference.ConfigPreferences
import top.wangchenyan.common.CommonApp
import top.wangchenyan.common.ext.getColorEx
import top.wangchenyan.common.ext.setLink
import top.wangchenyan.common.ext.showConfirmDialog
Expand All @@ -13,10 +20,6 @@ import top.wangchenyan.common.utils.LaunchUtils
import top.wangchenyan.common.widget.CustomSpan.appendStyle
import top.wangchenyan.common.widget.dialog.CenterDialog
import top.wangchenyan.common.widget.dialog.CenterDialogBuilder
import me.wcy.music.R
import me.wcy.music.account.AccountPreference
import me.wcy.music.databinding.DialogApiDomainBinding
import me.wcy.music.storage.preference.ConfigPreferences

/**
* Created by wangchenyan.top on 2023/9/18.
Expand Down Expand Up @@ -59,6 +62,9 @@ class ApiDomainDialog(private val context: Context) {
} else {
ConfigPreferences.apiDomain = domain
AccountPreference.clear()
CommonApp.appScope.launch {
NetCache.userCache.clear()
}
dialog.dismiss()
context.showSingleDialog("设置成功,重启后生效") {
AppUtils.relaunchApp(true)
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/me/wcy/music/common/bean/PlaylistData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ data class PlaylistData(
@SerializedName("ToplistType")
val toplistType: String = "",
) {
@SerializedName("_songList")
var songList: List<SongData> = emptyList()

fun getSmallCover(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,27 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import top.wangchenyan.common.ext.toUnMutable
import me.wcy.music.account.service.UserService
import me.wcy.music.common.bean.PlaylistData
import me.wcy.music.discover.DiscoverApi
import me.wcy.music.discover.banner.BannerData
import me.wcy.music.net.NetCache
import me.wcy.music.storage.preference.ConfigPreferences
import top.wangchenyan.common.ext.toUnMutable
import javax.inject.Inject

/**
* Created by wangchenyan.top on 2023/9/25.
*/
@HiltViewModel
class DiscoverViewModel @Inject constructor() : ViewModel() {
class DiscoverViewModel @Inject constructor(
private val userService: UserService
) : ViewModel() {
private val _bannerList = MutableStateFlow<List<BannerData>>(emptyList())
val bannerList = _bannerList.toUnMutable()

Expand All @@ -30,10 +34,8 @@ class DiscoverViewModel @Inject constructor() : ViewModel() {
private val _rankingList = MutableLiveData<List<PlaylistData>>(emptyList())
val rankingList = _rankingList.toUnMutable()

@Inject
lateinit var userService: UserService

init {
loadCache()
viewModelScope.launch {
userService.profile.collectLatest { profile ->
if (profile != null && ConfigPreferences.apiDomain.isNotEmpty()) {
Expand All @@ -45,12 +47,36 @@ class DiscoverViewModel @Inject constructor() : ViewModel() {
loadRankingList()
}

private fun loadCache() {
viewModelScope.launch {
val list = NetCache.globalCache.getJsonArray(CACHE_KEY_BANNER, BannerData::class.java)
?: return@launch
_bannerList.value = list
}
if (userService.isLogin()) {
viewModelScope.launch {
val list = NetCache.userCache.getJsonArray(
CACHE_KEY_REC_PLAYLIST,
PlaylistData::class.java
) ?: return@launch
_recommendPlaylist.value = list
}
}
viewModelScope.launch {
val list =
NetCache.globalCache.getJsonArray(CACHE_KEY_RANKING_LIST, PlaylistData::class.java)
?: return@launch
_rankingList.postValue(list)
}
}

private fun loadBanner() {
viewModelScope.launch {
kotlin.runCatching {
DiscoverApi.get().getBannerList()
}.onSuccess {
_bannerList.value = it.banners
NetCache.globalCache.putJson(CACHE_KEY_BANNER, it.banners)
}.onFailure {
}
}
Expand All @@ -62,6 +88,7 @@ class DiscoverViewModel @Inject constructor() : ViewModel() {
DiscoverApi.get().getRecommendPlaylists()
}.onSuccess {
_recommendPlaylist.value = it.playlists
NetCache.userCache.putJson(CACHE_KEY_REC_PLAYLIST, it.playlists)
}.onFailure {
}
}
Expand All @@ -73,20 +100,31 @@ class DiscoverViewModel @Inject constructor() : ViewModel() {
DiscoverApi.get().getRankingList()
}.onSuccess {
val rankingList = it.playlists.take(5)
_rankingList.value = rankingList
val deferredList = mutableListOf<Deferred<*>>()
rankingList.forEach {
val d = async {
val songListRes = kotlin.runCatching {
DiscoverApi.get().getPlaylistSongList(it.id, 3)
}
if (songListRes.getOrNull()?.code == 200) {
it.songList = songListRes.getOrThrow().songs
_rankingList.value = rankingList
}
}
deferredList.add(d)
}
deferredList.forEach { d ->
d.await()
}
_rankingList.postValue(rankingList)
NetCache.globalCache.putJson(CACHE_KEY_RANKING_LIST, rankingList)
}.onFailure {
}
}
}

companion object {
const val CACHE_KEY_BANNER = "discover_banner"
const val CACHE_KEY_REC_PLAYLIST = "discover_recommend_playlist"
const val CACHE_KEY_RANKING_LIST = "discover_ranking_list"
}
}
11 changes: 6 additions & 5 deletions app/src/main/java/me/wcy/music/mine/home/MineFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ import com.blankj.utilcode.util.SizeUtils
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import top.wangchenyan.common.ext.loadAvatar
import top.wangchenyan.common.ext.toast
import top.wangchenyan.common.ext.viewBindings
import top.wangchenyan.common.widget.decoration.SpacingDecoration
import top.wangchenyan.common.widget.dialog.BottomItemsDialogBuilder
import me.wcy.music.R
import me.wcy.music.account.service.UserService
import me.wcy.music.common.ApiDomainDialog
Expand All @@ -26,6 +21,11 @@ import me.wcy.music.mine.home.viewmodel.MineViewModel
import me.wcy.music.mine.playlist.UserPlaylistItemBinder
import me.wcy.radapter3.RAdapter
import me.wcy.router.CRouter
import top.wangchenyan.common.ext.loadAvatar
import top.wangchenyan.common.ext.toast
import top.wangchenyan.common.ext.viewBindings
import top.wangchenyan.common.widget.decoration.SpacingDecoration
import top.wangchenyan.common.widget.dialog.BottomItemsDialogBuilder
import javax.inject.Inject

/**
Expand All @@ -50,6 +50,7 @@ class MineFragment : BaseMusicFragment() {
initProfile()
initLocalMusic()
initPlaylist()
viewModel.updatePlaylistFromCache()
}

override fun onResume() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import top.wangchenyan.common.ext.toUnMutable
import top.wangchenyan.common.model.CommonResult
import top.wangchenyan.common.net.apiCall
import me.wcy.music.account.service.UserService
import me.wcy.music.common.bean.PlaylistData
import me.wcy.music.mine.MineApi
import me.wcy.music.net.NetCache
import top.wangchenyan.common.ext.toUnMutable
import top.wangchenyan.common.model.CommonResult
import top.wangchenyan.common.net.apiCall
import javax.inject.Inject

/**
Expand Down Expand Up @@ -46,6 +47,17 @@ class MineViewModel @Inject constructor() : ViewModel() {
}
}

fun updatePlaylistFromCache() {
viewModelScope.launch {
if (userService.isLogin()) {
val uid = userService.profile.value?.userId ?: return@launch
val cacheList = NetCache.userCache.getJsonArray(CACHE_KEY, PlaylistData::class.java)
?: return@launch
notifyPlaylist(uid, cacheList)
}
}
}

fun updatePlaylist() {
if (userService.isLogin()) {
val uid = userService.profile.value?.userId ?: return
Expand All @@ -61,14 +73,19 @@ class MineViewModel @Inject constructor() : ViewModel() {
}
if (res.getOrNull()?.code == 200) {
val list = res.getOrThrow().playlists
val mineList = list.filter { it.userId == uid }
_likePlaylist.value = mineList.firstOrNull()
_myPlaylists.value = mineList.takeLast((mineList.size - 1).coerceAtLeast(0))
_collectPlaylists.value = list.filter { it.userId != uid }
notifyPlaylist(uid, list)
NetCache.userCache.putJson(CACHE_KEY, list)
}
}
}

private fun notifyPlaylist(uid: Long, list: List<PlaylistData>) {
val mineList = list.filter { it.userId == uid }
_likePlaylist.value = mineList.firstOrNull()
_myPlaylists.value = mineList.takeLast((mineList.size - 1).coerceAtLeast(0))
_collectPlaylists.value = list.filter { it.userId != uid }
}

suspend fun removeCollect(id: Long): CommonResult<Unit> {
val res = apiCall { MineApi.get().collectPlaylist(id, 2) }
return if (res.isSuccess()) {
Expand All @@ -81,4 +98,8 @@ class MineViewModel @Inject constructor() : ViewModel() {
CommonResult.fail(res.code, res.msg)
}
}

companion object {
private const val CACHE_KEY = "my_playlist"
}
}
70 changes: 70 additions & 0 deletions app/src/main/java/me/wcy/music/net/NetCache.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package me.wcy.music.net

import com.blankj.utilcode.util.CacheDiskUtils
import com.blankj.utilcode.util.GsonUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

/**
* Created by wangchenyan.top on 2024/1/4.
*/
class NetCache(name: String) {
private val cache by lazy {
CacheDiskUtils.getInstance(name)
}

suspend fun getString(key: String): String {
return withContext(Dispatchers.IO) {
cache.getString(key, "")
}
}

suspend fun <T> getJsonObject(key: String, clazz: Class<T>): T? {
return withContext(Dispatchers.IO) {
val json = getString(key)
kotlin.runCatching {
GsonUtils.fromJson(json, clazz)
}.getOrNull()
}
}

suspend fun <T> getJsonArray(key: String, clazz: Class<T>): List<T>? {
return withContext(Dispatchers.IO) {
val json = getString(key)
top.wangchenyan.common.utils.GsonUtils.fromJsonList(json, clazz)
}
}

suspend fun putString(key: String, value: String) {
withContext(Dispatchers.IO) {
cache.put(key, value)
}
}

suspend fun putJson(key: String, json: Any) {
withContext(Dispatchers.IO) {
cache.put(key, GsonUtils.toJson(json))
}
}

suspend fun remove(key: String) {
withContext(Dispatchers.IO) {
cache.remove(key)
}
}

suspend fun clear() {
withContext(Dispatchers.IO) {
cache.clear()
}
}

companion object {
val userCache by lazy {
NetCache("net/user")
}
val globalCache by lazy {
NetCache("net/global")
}
}
}
2 changes: 1 addition & 1 deletion app/src/main/res/layout/fragment_mine.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/common_bg_image_placeholder_round" />
android:src="@drawable/ic_launcher_round" />
</FrameLayout>

<LinearLayout
Expand Down

0 comments on commit bf6f73e

Please sign in to comment.