Skip to content

Instantly share code, notes, and snippets.

@LennyLizowzskiy
Created June 5, 2023 12:57
Show Gist options
  • Save LennyLizowzskiy/51c9233d38b21c52b1b7b5a4b8ab57ff to your computer and use it in GitHub Desktop.
Save LennyLizowzskiy/51c9233d38b21c52b1b7b5a4b8ab57ff to your computer and use it in GitHub Desktop.
Android InputMethodService implementation that allows to build IME UI via Jetpack Compose
import android.content.Intent
import android.inputmethodservice.InputMethodService
import android.view.View
import androidx.annotation.CallSuper
import androidx.compose.ui.platform.AbstractComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ServiceLifecycleDispatcher
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.setViewTreeLifecycleOwner
import androidx.lifecycle.setViewTreeViewModelStoreOwner
import androidx.savedstate.SavedStateRegistry
import androidx.savedstate.SavedStateRegistryController
import androidx.savedstate.SavedStateRegistryOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
/*
* Dependencies:
* `androidx.compose.ui:ui`
* `androidx.lifecycle:lifecycle-common`
* `androidx.lifecycle:lifecycle-viewmodel`
* `androidx.lifecycle:lifecycle-service`
* `androidx.savedstate:savedstate`
*/
/**
* Base class for IME UI implemented via AndroidX Jetpack Compose
*
* @see InputMethodService
* @see AbstractComposeView
*/
@Suppress("LeakingThis")
abstract class ComposedInputMethodService : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner {
abstract fun onCreateInputComposeView(): AbstractComposeView
private val lifecycleDispatcher = ServiceLifecycleDispatcher(this)
override val lifecycle: Lifecycle
get() = lifecycleDispatcher.lifecycle
override val viewModelStore = ViewModelStore()
private val savedStateRegistryController = SavedStateRegistryController.create(this)
override val savedStateRegistry: SavedStateRegistry
get() = savedStateRegistryController.savedStateRegistry
@CallSuper
override fun onCreate() {
lifecycleDispatcher.onServicePreSuperOnCreate()
super.onCreate()
savedStateRegistryController.performRestore(null)
}
@CallSuper
override fun onBindInput() {
lifecycleDispatcher.onServicePreSuperOnBind()
super.onBindInput()
}
@CallSuper
override fun onCreateInputView(): View {
val view = onCreateInputComposeView().apply { // compose runtime exception when trying to create Abstract/ComposeView in abstract class
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnLifecycleDestroyed(lifecycle))
}
window?.window?.decorView?.let { decorView ->
decorView.setViewTreeLifecycleOwner(this)
decorView.setViewTreeViewModelStoreOwner(this)
decorView.setViewTreeSavedStateRegistryOwner(this)
}
return view
}
@CallSuper
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
@CallSuper
override fun onDestroy() {
lifecycleDispatcher.onServicePreSuperOnDestroy()
super.onDestroy()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment