【问题标题】:Jetpack Compose : Crash when adding view to window managerJetpack Compose:将视图添加到窗口管理器时崩溃
【发布时间】:2020-10-29 05:35:44
【问题描述】:

我尝试将 jetpack compose 视图添加到应用程序覆盖视图的窗口管理器。但是应用程序崩溃了。我使用以下代码添加了 jetpack compose 视图。当我尝试 XML 布局时,它工作正常。还有其他人遇到过这个问题吗?提前致谢。

private val overlayWindowManager by lazy {
    getSystemService(Context.WINDOW_SERVICE)
            as WindowManager
}

 private fun initWindowManager() {
    val params = WindowManager.LayoutParams(
        WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
        WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
        PixelFormat.TRANSLUCENT
    )
    params.gravity = Gravity.RIGHT or Gravity.TOP
    overlayWindowManager.addView(ComposeView(this).apply {
        setContent {  Text("WINDOW") }
    }, params)
}

错误日志

 java.lang.IllegalStateException: ViewTreeLifecycleOwner is not present in this window. Use ComponentActivity, FragmentActivity or AppCompatActivity to configure ViewTreeLifecycleOwner automatically, or call ViewTreeLifecycleOwner.set() for this View or an ancestor in the same window.
    at androidx.compose.ui.platform.AbstractComposeView.onAttachedToWindow(ComposeView.kt:176)
    at android.view.View.dispatchAttachedToWindow(View.java:20479)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3489)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2417)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
    at android.view.Choreographer.doCallbacks(Choreographer.java:796)
    at android.view.Choreographer.doFrame(Choreographer.java:731)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:223)
    at android.app.ActivityThread.main(ActivityThread.java:7656)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)

【问题讨论】:

    标签: android android-jetpack-compose


    【解决方案1】:

    ComposeView 需要 LifecycleOwner,但我们这里没有,所以我们必须创建它。

    internal class MyLifecycleOwner : SavedStateRegistryOwner {
    
        private var mLifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)
        private var mSavedStateRegistryController: SavedStateRegistryController = SavedStateRegistryController.create(this)
    
        val isInitialized: Boolean
            get() = true
    
        override fun getLifecycle(): Lifecycle {
            return mLifecycleRegistry
        }
    
        fun setCurrentState(state: Lifecycle.State) {
            mLifecycleRegistry.currentState = state
        }
    
        fun handleLifecycleEvent(event: Lifecycle.Event) {
            mLifecycleRegistry.handleLifecycleEvent(event)
        }
    
        override fun getSavedStateRegistry(): SavedStateRegistry {
            return mSavedStateRegistryController.savedStateRegistry
        }
    
        fun performRestore(savedState: Bundle?) {
            mSavedStateRegistryController.performRestore(savedState)
        }
    
        fun performSave(outBundle: Bundle) {
            mSavedStateRegistryController.performSave(outBundle)
        }
    }
    

    然后使用MyLifecycleOwner作为composeView的ViewTreeLifecycleOwner。

    private fun initWindowManager() {
        val params = ...
        val composeView = ComposeView(context = context)
        composeView.setContent { . . . }
    
        val lifecycleOwner = MyLifecycleOwner()
        lifecycleOwner.performRestore(null)
        lifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
        ViewTreeLifecycleOwner.set(composeView, lifecycleOwner)
        ViewTreeSavedStateRegistryOwner.set(composeView, lifecycleOwner)
    
        val viewModelStore = ViewModelStore()
        ViewTreeViewModelStoreOwner.set(composeView) { viewModelStore }
    
        overlayWindowManager.addView(composeView, params) 
    }
    

    您可以在这里查看更多详细信息https://gist.github.com/handstandsam/6ecff2f39da72c0b38c07aa80bbb5a2f

    【讨论】:

      【解决方案2】:

      使用ViewTreeLifecycleOwner.set():

      windowManager.addView(ComposeView(this).apply {
          ViewTreeLifecycleOwner.set(this, activity)
          setContent {  Text("WINDOW") }
      }, params)
      

      【讨论】:

        【解决方案3】:

        您的主要活动扩展了哪个类? 看起来您的答案在堆栈跟踪的第一行 Use ComponentActivity, FragmentActivity or AppCompatActivity to configure ViewTreeLifecycleOwner automatically

        call ViewTreeLifecycleOwner.set() for this View or an ancestor in the same window

        【讨论】:

          猜你喜欢
          • 2014-05-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多