android 在设备旋转时保持标签状态

问题描述 投票:0回答:1

我正在构建具有片段的 Android 应用程序,并且该应用程序使用 MVVM 设计模式。 每个片段代表一个足球联赛标题和图标 这些选项卡根据 API 调用动态添加。

这里是API调用签名调用

@GET("/leagues")
    suspend fun getLeague(
        @Query("id")
        leagueId: Int = Shared.LEAGUES_IDS[0],
        @Query("current")
        current: String = "true"
    ): Response<Leagues>

这是用于调用 API 和存储数据的视图模型类

    @HiltViewModel
class FootBallViewModel @Inject constructor(
    private val app: Application,
    private val remoteRepository: RemoteRepository,
    private val defaultLocalRepository: DefaultLocalRepository
): ViewModel() {
    var apiCounter = 0
    val leagues: MutableList<Leagues> = mutableListOf()
    private val _leaguesMutableLiveData = MutableLiveData<ResponseState<Leagues>>()
    val leaguesMutableLiveData: LiveData<ResponseState<Leagues>> = _leaguesMutableLiveData

init {
        viewModelScope.launch(Dispatchers.IO) {
            if(Shared.isConnected) {
                Shared.LEAGUES_IDS.forEach { leagueId ->
                    when(val responseState = getLeague(leagueId)) { //here's the call of league API
                        is ResponseState.Success -> {
                            if(Shared.isLiveMatches)
                                responseState.data?.body()?.response?.get(0)?.seasons?.get(0)?.year?.let { season ->
                                    getLeagueMatches(
                                        leagueId,
                                        season,
                                        app.getString(R.string.live_matches)
                                    )
                                }
                            else
                                responseState.data?.body()?.response?.get(0)?.seasons?.get(0)?.year?.let { season ->
                                    getLeagueMatches(
                                        leagueId,
                                        season,
                                        null
                                    )
                                }
                        }
                        is ResponseState.Loading -> {}
                        is ResponseState.Error -> {}
                    }
                }
            }
        }
    }

suspend fun getLeague(id: Int): ResponseState<Response<Leagues>> = viewModelScope.async(Dispatchers.IO) {
        if (Shared.isConnected) {
            try {
                val response = remoteRepository.getLeague(id)
                response?.body()?.let { leagues.add(it) }
                _leaguesMutableLiveData.postValue(ResponseState.Success(response?.body()!!))
                apiCounter++
                Log.i("apiCounter", apiCounter.toString())
                return@async ResponseState.Success(response)
            } catch (exception: Exception) {
                _leaguesMutableLiveData.postValue(ResponseState.Error(app.getString(R.string.unknown_error)))
                handleLeaguesException(exception)
                return@async ResponseState.Error(app.getString(R.string.unknown_error))
            }
        }
        else {
            _leaguesMutableLiveData.postValue(ResponseState.Error(app.getString(R.string.unknown_error)))
            return@async ResponseState.Error(app.getString(R.string.unable_to_connect))
        }
    }.await()

    ....
} //end of view model class

最后这是我动态添加选项卡的方法

footBallViewModel.leaguesMutableLiveData.observe(viewLifecycleOwner) {
            TabItemBinding.inflate(layoutInflater).apply {
                this.league = it.data?.response?.get(0)?.league
                val tab = tabLayout.newTab().setCustomView(this.root)
                tabLayout.addTab(tab)
                val animation = AnimationUtils.loadAnimation(context, R.anim.slide_in)
                tab.customView?.startAnimation(animation)
            }
        Log.i("tabsCount", tabLayout.tabCount.toString())
    }

问题定义: 现在选项卡已完美添加,但当我旋转设备时问题就出现了,因为

leaguesMutableLiveData
仅保存最后存储的联赛项目,选项卡布局仅从
leaguesMutableLiveData

获取最后一个选项卡

我尝试过的其他解决方案: 我试图让

leaguesMutableLiveData
保持
MutableList<League>
但这不起作用,因为每次我向列表中添加联赛时,观察者总是添加额外的选项卡,因为观察者从第一个元素开始循环联赛列表。

所以简而言之,问题是如何根据联赛列表动态添加选项卡,并即使在设备符号上也保持选项卡状态?

android mvvm tabs android-viewmodel
1个回答
0
投票

这个想法是在联赛 API 的所有调用完成后发布联赛列表。

在下面的代码片段中请注意

class FootBallViewModel @Inject constructor(
    private val app: Application,
    private val remoteRepository: RemoteRepository,
    private val defaultLocalRepository: DefaultLocalRepository
  ): ViewModel() {
    val leagues: MutableList<League> = mutableListOf()
    private val _leaguesMutableLiveData = MutableLiveData<MutableList<League>>()
    val leaguesLiveData: LiveData<MutableList<League>> = _leaguesMutableLiveData
    init {
        viewModelScope.launch(Dispatchers.IO) {
            if(Shared.isConnected) {
                Shared.LEAGUES_IDS.forEach { leagueId ->
                    when(val responseState = getLeague(leagueId)) {
                        is ResponseState.Success -> {
                            if(Shared.isLiveMatches)
                                responseState.data?.body()?.response?.get(0)?.seasons?.get(0)?.year?.let { season ->
                                    getLeagueMatches(
                                        leagueId,
                                        season,
                                        app.getString(R.string.live_matches)
                                    )
                                }
                            else
                                responseState.data?.body()?.response?.get(0)?.seasons?.get(0)?.year?.let { season ->
                                    getLeagueMatches(
                                        leagueId,
                                        season,
                                        null
                                    )
                                }
                        }
                        is ResponseState.Loading -> {}
                        is ResponseState.Error -> {}
                    }
                }
                _leaguesMutableLiveData.postValue(leagues)
            }
        }
    }

suspend fun getLeague(id: Int): ResponseState<Response<League>?> = viewModelScope.async(Dispatchers.IO) {
        if (Shared.isConnected) {
            try {
                val response = remoteRepository.getLeague(id)
                response?.body()?.let { leagues.add(it) }
                return@async ResponseState.Success(response)
            } catch (exception: Exception) {
                handleLeaguesException(exception)
                return@async ResponseState.Error(app.getString(R.string.unknown_error))
            }
        }
        else {
            return@async ResponseState.Error(app.getString(R.string.unable_to_connect))
        }
    }.await()

   .....
} //end of view model class

发生什么事了?

  1. 我们添加一个列表变量

    val leagues: MutableList<League> = mutableListOf()
    ,它保存从
    getLeague(id: Int)

    返回的所有联赛
  2. 我们添加两个实时数据变量来保存我们的联赛列表

    //用于封装 私有 val _leaguesMutableLiveData = MutableLiveData()
    val leaguesLiveData:LiveData = _leaguesMutableLiveData

  3. 在此函数体内

    getLeague(id: Int)
    我们通过以下代码行将返回的联赛添加到列表中

    val 响应=remoteRepository.getLeague(id) 响应?.body()?.let { leagues.add(it) }

  4. 最后,循环联赛 ID 后

    Shared.LEAGUES_IDS.forEach { leagueId -> 当(val responseState = getLeague(leagueId))

.... } //for循环结束

然后我们将最终列表添加到我们的可变实时数据对象中,如下所示

_leaguesMutableLiveData.postValue(leagues)
© www.soinside.com 2019 - 2024. All rights reserved.