正在 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)
}
}
我假设它不会重组,因为更改的参数(
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")
}
}