撰写视图不会在状态更改时重新组合

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

正在 github 上研究 Neo Launcher Feeder

发现一个问题,即尽管状态发生变化,

ComposeOverlayView
中的撰写视图并未重新组合。我修改了
setContent
中的
onCreate
来专门针对和解决这个问题,并明确地将
LifecycleOwner
接口添加到类中。

总体上实现了所有应该使可组合项重构的接口

LifecycleOwner, SavedStateRegistryOwner, ViewModelStoreOwner

尝试了各种解决方案,包括Jetpack Compose,使用自定义Lifecycle/ViewModelStore/SavedStateRegistry Owner时不会触发重组


/*
 * This file is part of Neo Feed
 * Copyright (c) 2023   Saul Henriquez <[email protected]>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package com.saulhdev.feeder.overlay

import android.content.Context
import android.os.Bundle
import android.view.View
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.result.ActivityResultRegistry
import androidx.activity.result.ActivityResultRegistryOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.appcompat.view.ContextThemeWrapper
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.setViewTreeLifecycleOwner
import androidx.lifecycle.setViewTreeViewModelStoreOwner
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import androidx.savedstate.SavedStateRegistry
import androidx.savedstate.SavedStateRegistryController
import androidx.savedstate.SavedStateRegistryOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
import com.google.android.libraries.gsa.d.a.OverlayController
import com.saulhdev.feeder.NFApplication
import com.saulhdev.feeder.R
import com.saulhdev.feeder.compose.pages.OverlayPage
import com.saulhdev.feeder.theme.AppTheme
import org.kodein.di.DI
import org.kodein.di.DIAware
import org.kodein.di.android.closestDI
import org.kodein.di.compose.withDI

class ComposeOverlayView(val context: Context) :
    OverlayController(context, R.style.AppTheme, R.style.WindowTheme), LifecycleOwner,
    SavedStateRegistryOwner, ViewModelStoreOwner, OnBackPressedDispatcherOwner,
    ActivityResultRegistryOwner, DIAware {
    private lateinit var rootView: View
    private lateinit var composeView: ComposeView
    private lateinit var navController: NavHostController
    private val lifecycleRegistry = LifecycleRegistry(this)
    override val lifecycle: Lifecycle get() = lifecycleRegistry
    override val onBackPressedDispatcher: OnBackPressedDispatcher
        get() = OnBackPressedDispatcher()

    private val savedStateRegistryController = SavedStateRegistryController.create(this)
    override val savedStateRegistry: SavedStateRegistry
        get() = savedStateRegistryController.savedStateRegistry
    private val parentDI: DI by closestDI()
    override val di: DI by DI.lazy { extend(parentDI) }

    init {
        savedStateRegistryController.performAttach()
        savedStateRegistryController.performRestore(null)
        lifecycleRegistry.currentState = Lifecycle.State.STARTED
    }

    override fun onCreate(bundle: Bundle?) {
        super.onCreate(bundle)
        rootView = View.inflate(
            ContextThemeWrapper(this, R.style.AppTheme),
            R.layout.compose_overlay,
            container
        )
        lifecycleRegistry.currentState = Lifecycle.State.CREATED
        rootView.setViewTreeSavedStateRegistryOwner(this)
        rootView.setViewTreeLifecycleOwner(this)
        rootView.setViewTreeViewModelStoreOwner(this)
        rootView.setViewTreeOnBackPressedDispatcherOwner(this)
        composeView = rootView.findViewById(R.id.compose_view)
        composeView.setContent {
            navController = rememberNavController()
            AppTheme {
                var t by remember {
                    mutableStateOf(false)
                }
                androidx.compose.material3.Surface {
                    androidx.compose.material3.Button(onClick = {
                        t = !t
                    }) {
                        androidx.compose.material3.Text(text = "Start: $t")
                    }
                }
            }

        }
    }

    override fun onDestroy() {
        super.onDestroy()
        lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
    }

    override fun onResume() {
        super.onResume()
        lifecycleRegistry.currentState = Lifecycle.State.RESUMED
    }

    override val viewModelStore: ViewModelStore
        get() = ViewModelStore()
    override val activityResultRegistry: ActivityResultRegistry
        get() = NFApplication.mainActivity!!.activityResultRegistry

}

类似问题的链接

如何在服务中使用 Jetpack Compose(浮动窗口)

InputMethodService 与 Jetpack Compose - ComposeView 导致:组合到不传播 ViewTreeLifecycleOwner 的视图中

编辑24年9月1日 在撰写中添加了一个生命周期观察者

setContent
,正如预期的那样,它没有被调用

DisposableEffect(lifecycleOwner) {
   val observer = object : LifecycleObserver {
       @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
       fun onResume() {
           Log.v(TAG,"onResume Compose")
       }
   }

   lifecycleOwner.lifecycle.addObserver(observer)

   onDispose {
        lifecycleOwner.lifecycle.removeObserver(observer)
   }
}
android android-jetpack-compose android-lifecycle
1个回答
0
投票

我假设它不会重组,因为更改的参数(

t
)只能在字符串内访问。尝试将按钮移动到可组合函数中并传递
t
作为参数,如下所示:

composeView.setContent {
     navController = rememberNavController()
     AppTheme {
            var t by remember {
                mutableStateOf(false)
            }
            androidx.compose.material3.Surface {
                MyButton(t)
            }
     }
}


// ...

@Composable
fun MyButton(param: Boolean) {
   androidx.compose.material3.Button(onClick = {
         param = !param
   }) {
         androidx.compose.material3.Text(text = "Start: $param")
   }
}
© www.soinside.com 2019 - 2024. All rights reserved.