kotlin:Internal Error occurred while analyzing this expression - kotlin

I am using navigation safeargs for passing arguments from one Fragment to another .
However , after I rebuild the project ,I could not parse the augument I had sent .I got an error below:
Internal Error occurred while analyzing this expression:
org.jetbrains.kotlin.descriptors.InvalidModuleException: Accessing invalid module descriptor <production sources for module FavDishKT.app> is a module[ModuleDescriptorImpl#10578057]
at org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl.assertValid(ModuleDescriptorImpl.kt:62)
at org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl.getPackage(ModuleDescriptorImpl.kt:84)
at org.jetbrains.kotlin.resolve.lazy.FileScopeFactory.createScopesForFile(FileScopeFactory.kt:62)
at org.jetbrains.kotlin.resolve.lazy.FileScopeFactory.createScopesForFile$default(FileScopeFactory.kt:61)
at org.jetbrains.kotlin.resolve.lazy.FileScopeProviderImpl$cache$1.invoke(FileScopeProvider.kt:48)
at org.jetbrains.kotlin.resolve.lazy.FileScopeProviderImpl$cache$1.invoke(FileScopeProvider.kt:46)
at org.jetbrains.kotlin.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:578)
at org.jetbrains.kotlin.storage.LockBasedStorageManager$MapBasedMemoizedFunctionToNotNull.invoke(LockBasedStorageManager.java:651)
at org.jetbrains.kotlin.resolve.lazy.FileScopeProviderImpl.getFileScopes(FileScopeProvider.kt:53)
at org.jetbrains.kotlin.resolve.lazy.FileScopeProvider$DefaultImpls.getFileResolutionScope(FileScopeProvider.kt:30)
at org.jetbrains.kotlin.resolve.lazy.FileScopeProviderImpl.getFileResolutionScope(FileScopeProvider.kt:40)
at org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProviderImpl.getResolutionScopeForDeclaration(DeclarationScopeProviderImpl.java:60)
at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor.getOuterScope(LazyClassDescriptor.java:353)
at org.jetbrains.kotlin.resolve.lazy.descriptors.ClassResolutionScopesSupport$scopeForClassHeaderResolution$1.invoke(ClassResolutionScopesSupport.kt:44)
at org.jetbrains.kotlin.resolve.lazy.descriptors.ClassResolutionScopesSupport$scopeForClassHeaderResolution$1.invoke(ClassResolutionScopesSupport.kt:43)
at org.jetbrains.kotlin.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageM...
My configures:
build.gradle(project:FavDishKT)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.5.0"
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
def nav_version = "2.3.2"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
**build.gradle(Module:FavDishKT.app)**
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
// For more details visit https://developer.android.com/guide/navigation/navigation-pass-data#Safe-args
id 'androidx.navigation.safeargs.kotlin'
id 'kotlin-parcelize'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.gearsrun.favdishkt"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
packagingOptions {
exclude 'META-INF/atomicfu.kotlin_module'
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation("androidx.recyclerview:recyclerview:1.2.1")
// For control over item selection of both touch and mouse driven selection
implementation("androidx.recyclerview:recyclerview-selection:1.1.0")
implementation 'com.airbnb.android:lottie:3.4.1'
implementation 'de.hdodenhof:circleimageview:3.1.0'
implementation 'com.makeramen:roundedimageview:2.3.0'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation("com.squareup.okhttp3:okhttp:4.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
implementation 'com.google.code.gson:gson:2.8.7'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.github.bumptech.glide:glide:4.12.0'
kapt 'com.github.bumptech.glide:compiler:4.12.0'
}
dependencies {
//room
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
}
My idea is to pass the dish item from the homepage to another details page ,as follow ,Therefor ,I will need to pass a entity which names :FavDish
FavDish entity:
#Parcelize
#Entity(tableName = "fav_dishes_table")
data class FavDish(
#PrimaryKey(autoGenerate = true) val id:Int = 0,
#ColumnInfo val image:String,
#ColumnInfo(name = "image_source")val imageSource:String,
#ColumnInfo val title:String,
#ColumnInfo val type:String,
#ColumnInfo val category:String,
#ColumnInfo val ingredients:String,
#ColumnInfo(name = "cooking_time") val cookingTime:String,
#ColumnInfo(name = "instructions") val directionToCook:String,
#ColumnInfo(name = "favorite_dish") var favoriteDish:Boolean = false,
):Parcelable
And then , I have modified the navigation.xml ,from the AllDishes page to the DishDetailsFragment , and pass the entity reference as aguments :
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/mobile_navigation"
app:startDestination="#+id/navigation_all_dishes">
<fragment
android:id="#+id/navigation_all_dishes"
android:name="com.gearsrun.favdishkt.view.fragments.AllDishesFragment"
android:label="Home"
tools:layout="#layout/fragment_all_dishes" >
<action
android:id="#+id/action_navigation_all_dishes_to_dishDetailsFragment"
app:destination="#id/dishDetailsFragment" />
</fragment>
<fragment
android:id="#+id/navigation_favorite_dishes"
android:name="com.gearsrun.favdishkt.view.fragments.FavoriteFragment"
android:label="Favorite"
tools:layout="#layout/fragment_favorite_dishes" >
<action
android:id="#+id/action_navigation_favorite_dishes_to_dishDetailsFragment"
app:destination="#id/dishDetailsFragment" />
</fragment>
<fragment
android:id="#+id/navigation_random_dish"
android:name="com.gearsrun.favdishkt.view.fragments.RandomFragment"
android:label="Random"
tools:layout="#layout/fragment_random_dish" />
<fragment
android:id="#+id/dishDetailsFragment"
android:name="com.gearsrun.favdishkt.view.fragments.DishDetailsFragment"
android:label="fragment_dish_details"
tools:layout="#layout/fragment_dish_details" >
<argument
android:name="dishDetails"
app:argType="com.gearsrun.favdishkt.model.entities.FavDish"/>
</fragment>
</navigation>
From my AllDishsFragment (home page ) ,I use findNavController,and navigate to the detailsDishFragment ,and pass the entity to it :
class AllDishesFragment : Fragment(){
private var _binding: FragmentAllDishesBinding? = null
private val binding get() = _binding!!
private val mFavDishViewModel :FavDishViewModel by viewModels{
FavDishViewModelFactory((requireActivity().application as FavDishApplication).repository)
}
private lateinit var mFavDishAdapter: FavDishAdapter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentAllDishesBinding.inflate(inflater, container, false)
val root: View = binding.root
binding.imgAddHome.setOnClickListener {
val intent = Intent(context,AddUpdateActivity::class.java)
startActivity(intent)
}
binding.rvHome.layoutManager = GridLayoutManager(requireActivity(),2)
mFavDishAdapter = FavDishAdapter(this)
binding.rvHome.adapter = mFavDishAdapter
mFavDishViewModel.allDishesList.observe(viewLifecycleOwner){dishes->
dishes.let{
if(it.isNotEmpty()){
binding.rvHome.visibility=View.VISIBLE
binding.txtNotice.visibility=View.GONE
mFavDishAdapter.getAllDishes(it)
}else{
binding.rvHome.visibility =View.GONE
binding.txtNotice.visibility=View.VISIBLE
}
}
}
return root
}
fun dishDetails(favDish: FavDish){
if(requireActivity() is MainActivity){
(activity as MainActivity?)!!.hideBottomNavigationView()
}
findNavController().navigate(AllDishesFragmentDirections.actionNavigationAllDishesToDishDetailsFragment(favDish))
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
And the DetailDishFragment ,where it should receive the args and parse it occured the error :
class DishDetailsFragment : Fragment() {
private val mFavDishViewModel : FavDishViewModel by viewModels{
FavDishViewModelFactory((requireActivity().application as FavDishApplication).repository)
}
private var mBinding : FragmentDishDetailsBinding? =null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
mBinding = FragmentDishDetailsBinding.inflate(inflater,container,false)
return mBinding!!.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val args:DishDetailsFragmentArgs by navArgs()
args.let{
try {
Glide.with(requireActivity())
.load(it.dishDetails.image)
}catch(e: IOException){
}
}
}
}
And the problem description :
Internal Error occurred while analyzing this expression:
org.jetbrains.kotlin.descriptors.InvalidModuleException: Accessing invalid module descriptor <production sources for module FavDishKT.app> is a module[ModuleDescriptorImpl#10578057]
at org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl.assertValid(ModuleDescriptorImpl.kt:62)
at org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl.getPackage(ModuleDescriptorImpl.kt:84)
at org.jetbrains.kotlin.resolve.lazy.FileScopeFactory.createScopesForFile(FileScopeFactory.kt:62)
at org.jetbrains.kotlin.resolve.lazy.FileScopeFactory.createScopesForFile$default(FileScopeFactory.kt:61)
at org.jetbrains.kotlin.resolve.lazy.FileScopeProviderImpl$cache$1.invoke(FileScopeProvider.kt:48)
at org.jetbrains.kotlin.resolve.lazy.FileScopeProviderImpl$cache$1.invoke(FileScopeProvider.kt:46)
at org.jetbrains.kotlin.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:578)
at org.jetbrains.kotlin.storage.LockBasedStorageManager$MapBasedMemoizedFunctionToNotNull.invoke(LockBasedStorageManager.java:651)
at org.jetbrains.kotlin.resolve.lazy.FileScopeProviderImpl.getFileScopes(FileScopeProvider.kt:53)
at org.jetbrains.kotlin.resolve.lazy.FileScopeProvider$DefaultImpls.getFileResolutionScope(FileScopeProvider.kt:30)
at org.jetbrains.kotlin.resolve.lazy.FileScopeProviderImpl.getFileResolutionScope(FileScopeProvider.kt:40)
at org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProviderImpl.getResolutionScopeForDeclaration(DeclarationScopeProviderImpl.java:60)
at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor.getOuterScope(LazyClassDescriptor.java:353)
at org.jetbrains.kotlin.resolve.lazy.descriptors.ClassResolutionScopesSupport$scopeForClassHeaderResolution$1.invoke(ClassResolutionScopesSupport.kt:44)
at org.jetbrains.kotlin.resolve.lazy.descriptors.ClassResolutionScopesSupport$scopeForClassHeaderResolution$1.invoke(ClassResolutionScopesSupport.kt:43)
at org.jetbrains.kotlin.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageM...
Could anyone helps ?Thank you so much in advance !!

install and uninstall kotlin plugin.it Worked for me

For My case, I had the same issue but it was only happening in one particular project, The rest were okay so I tried upgrading the build Gradle plugin of the specific project to 7.3.0 and It worked. You can try to see if this helps

Invalid Cache Restart with both vcs and system cache option selected can resolved this issue. It worked for me.
Update: These warnings frequently coming in Dolphin Version of Android Studio(stable) causing faliure of auto suggestion and layout rendering. If you want to get rid of them for stable version you can use Chipmunk version or try canary channels of dolphin.

Updating ktx implementation and syncing gradle worked for me!

Related

Jetpack Compose - unresolved refence when using viewmodel value in LazyColumn

For my college project I want to use data from Firestore, and then use MVVM pattern to display the items on the Lazy Column.
Here is the code of the screen of where I want the values of viewmodel to be displayed:
fun HomeScreen (navController: NavController, viewModel: ArticleViewModel = hiltViewModel()){
var expanded = remember { mutableStateOf(false) }
val articleResponse = viewModel.articleState.value
Scaffold() {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
) {
items(items = articleResponse.data) {
ArticleList(model = it) { model ->
Log.d("TAG", "Clicked on $model")
navController.navigate(route = NavScreens.DetailScreen.name +"/$model")
}
}
}
}
}
Here is the field of where exactly I get the error that is I mentioned in the title:
here
Previously I used an array to display the item in the LazyColumn and it worked normally.
Perhaps, the problem lies in the ViewModel? Here is the ViewModel that I'm using:
#HiltViewModel
class ArticleViewModel #Inject constructor(
private val useCases: UseCases
):ViewModel() {
private val _articleState = mutableStateOf<Response<List<Article>>>(Response.Loading)
val articleState: State<Response<List<Article>>> = _articleState
init {
getArticles()
}
private fun getArticles() {
viewModelScope.launch {
useCases.getArticle().collect { response ->
_articleState.value = response
}
}
}
}
When I tried searching for the solution, I've read that the problem could be with the dependencies/plugins, I have tried changing couple of the dependencies but the issue still persists. I've heard that some of the plugins doesn't work with others since I'm new to jetpack compose it is harder for me to identify the issues within the dependencies.
Here is my Gradle files:
buildscript {
ext {
compose_version = '1.0.1'
hilt_version = "2.40.5"
gradle_version = "7.2.0"
kotlin_version = "1.6.20"
coroutines_version = "1.6.1"
google_services_version = "4.3.10"
hilt_version = "2.40.5"
core_version = "1.7.0"
appcompat_version = "1.4.1"
live_data_version = "2.4.1"
activity_compose_version = "1.4.0"
material_version = "1.6.0"
hilt_navigation_compose_version = "1.0.0"
firebase_bom_version = "30.0.0"
}
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.google.gms:google-services:4.3.4'
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
classpath "com.android.tools.build:gradle:$gradle_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.gms:google-services:$google_services_version"
}
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.1.3' apply false
id 'com.android.library' version '7.1.3' apply false
id 'org.jetbrains.kotlin.android' version '1.5.21' apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
}
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.google.gms.google-services'
id 'dagger.hilt.android.plugin'
id 'kotlin-kapt'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.example.flow"
minSdk 28
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
kotlinCompilerVersion '1.5.21'
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
implementation "androidx.compose.compiler:compiler:1.0.0-beta08"
implementation 'androidx.core:core-ktx:1.7.0'
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.3.0-alpha02'
implementation "androidx.appcompat:appcompat:$appcompat_version"
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation "androidx.core:core-splashscreen:1.0.0-beta02"
implementation "androidx.navigation:navigation-compose:2.4.0-alpha10"
implementation("io.coil-kt:coil-compose:2.1.0")
implementation "com.google.firebase:firebase-firestore:22.0.1"
implementation "com.google.dagger:hilt-android:$hilt_version"
implementation platform("com.google.firebase:firebase-bom:$firebase_bom_version")
implementation "com.google.firebase:firebase-firestore-ktx"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
kapt "androidx.hilt:hilt-compiler:1.0.0"
implementation "androidx.hilt:hilt-navigation-compose:$hilt_navigation_compose_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutines_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$live_data_version"
}
I would be grateful if you are able to assist me on finding the solution.
The problem is that articleState.value is Response not List. You can do something like that:
val articleResponse = viewModel.articleState.value
when (articleResponse) {
Response.Loading -> <LoadingComponenet />
Response.Error -> <ErrorComponent />
Response.Success -> Scaffold() {
.............
}
}

java.lang.IllegalStateException :ViewTreeLifecycleOwner not found from DecorView#5ab7e30[MainActivity]

i followed this documentation for including a ComposeView directly inside a fragment without xml layout inflating , but it giving java.lang.IllegalStateException.
please help me to fix this issue.
Android Studio: 2020.3.1 canary 14
compose_version :'1.0.0-beta01'
this is Fragment's code:
class RecipeListFragment : Fragment() {
private lateinit var viewModel: RecipeListViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return ComposeView(requireContext()).apply {
setContent {
Column(
modifier = Modifier
.padding(16.dp)
) {
Text(
text = "Recipe List",
style = MaterialTheme.typography.h3
)
}
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this).get(RecipeListViewModel::class.java)
}
}
this is run time error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.mvvmrecepiapp, PID: 18722
java.lang.IllegalStateException: ViewTreeLifecycleOwner not found from DecorView#5ab7e30[MainActivity]
at androidx.compose.ui.platform.WindowRecomposer_androidKt.createLifecycleAwareViewTreeRecomposer(WindowRecomposer.android.kt:214)
at androidx.compose.ui.platform.WindowRecomposer_androidKt.access$createLifecycleAwareViewTreeRecomposer(WindowRecomposer.android.kt:1)
at androidx.compose.ui.platform.WindowRecomposerFactory$Companion$LifecycleAware$1.createRecomposer(WindowRecomposer.android.kt:97)
at androidx.compose.ui.platform.WindowRecomposerPolicy.createAndInstallWindowRecomposer$ui_release(WindowRecomposer.android.kt:152)
at androidx.compose.ui.platform.WindowRecomposer_androidKt.getWindowRecomposer(WindowRecomposer.android.kt:200)
at androidx.compose.ui.platform.AbstractComposeView.ensureCompositionCreated(ComposeView.android.kt:200)
at androidx.compose.ui.platform.AbstractComposeView.onAttachedToWindow(ComposeView.android.kt:235)
at android.view.View.dispatchAttachedToWindow(View.java:19553)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3430)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2028)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1721)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7598)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
at android.view.Choreographer.doCallbacks(Choreographer.java:790)
at android.view.Choreographer.doFrame(Choreographer.java:725)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:951)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
UPDATE:
here is my build.gradle(:app)
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdk 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.mvvmrecepiapp"
minSdk 21
targetSdk 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
useIR = true
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
kotlinCompilerVersion '1.4.32'
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'com.google.android.material:material:1.3.0'
// compose_version = "1.0.0-beta01" variable in project level build.gradle
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation 'androidx.activity:activity-compose:1.3.0-alpha06'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
def fragment_version = "1.3.2"
implementation "androidx.fragment:fragment-ktx:$fragment_version"
def nav_version = "2.3.5"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.0.0-beta04"
}
The support for ViewTreeLifecycleOwner was introduced in the AppCompat with the version 1.3.0.
Currently the latest AppCompat release is
implementation 'androidx.appcompat:appcompat:1.3.0'

Can't import androidx.datastore.dataStore (trying to recreate Google Codelab Example)

Problem:
I'm trying to recreate this codelab tutorial project https://developer.android.com/codelabs/android-proto-datastore, but Android Studio can't import androidx.datastore.dataStore
Steps:
create new Kotlin project with an empty Acivity
modify gradle file
Switch to Android Studio's Project view
create a folder named proto inside of app/src/main
create and modify file user_prefs.proto inside of app/src/main/proto
Build -> Clean Project -> rebuild project
Create a serializer class called UserPreferencesSerializer
Trying to add the following Code to the empty MainActivity.kt
private const val DATA_STORE_FILE_NAME = "user_prefs.pb"
private val Context.userPreferencesStore: DataStore
by dataStore(
fileName = DATA_STORE_FILE_NAME,
serializer = UserPreferencesSerializer )
After this step Android Studio marks dataStore and shows the warning "Unresolved reference: dataStore" I'm also unable to import androidx.datastore.dataStore, but I can't find a missing import in my gradle file. Please, can someone tell me how I can resolve this problem?
Code:
build.gradle
plugins {
id 'com.android.application'
id 'kotlin-android'
id "com.google.protobuf" version "0.8.12"
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.example.test"
minSdkVersion 28
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation "androidx.datastore:datastore-core:1.0.0-alpha08"
implementation "com.google.protobuf:protobuf-javalite:3.11.0"
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.10.0"
}
// Generates the java Protobuf-lite code for the Protobufs in this project. See
// https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
// for more information.
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option 'lite'
}
}
}
}
}
user_prefs.proto
syntax = "proto3";
option java_package = "com.example.test";
option java_multiple_files = true;
message UserPreferences {
// filter for showing / hiding completed tasks
bool show_completed = 1;
}
UserPreferencesSerializer
package com.example.test
import androidx.datastore.core.CorruptionException
import androidx.datastore.core.Serializer
import com.google.protobuf.InvalidProtocolBufferException
import java.io.InputStream
import java.io.OutputStream
object UserPreferencesSerializer : Serializer<UserPreferences> {
override val defaultValue: UserPreferences = UserPreferences.getDefaultInstance()
override suspend fun readFrom(input: InputStream): UserPreferences {
try {
return UserPreferences.parseFrom(input)
} catch (exception: InvalidProtocolBufferException) {
throw CorruptionException("Cannot read proto.", exception)
}
}
override suspend fun writeTo(t: UserPreferences, output: OutputStream) = t.writeTo(output)
}
MainActivity.kt
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.datastore.core.DataStore
private const val DATA_STORE_FILE_NAME = "user_prefs.pb"
private val Context.userPreferencesStore: DataStore<UserPreferences> by dataStore(
fileName = DATA_STORE_FILE_NAME,
serializer = UserPreferencesSerializer
)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
I also had this problem while working on a project.
I found that I was using datastore-core and needed datastore-preferences. So I changed my dependency declaration from:
implementation 'androidx.datastore:datastore-core:1.0.0-alpha08'
to:
implementation 'androidx.datastore:datastore-preferences:1.0.0'
Possibly there was a breaking change between alpha08 and the 1.0.0 release.
The dataStore delegate is part of the androidx.datastore:datastore library.
Add the dependency to your modudle's build.gradle file. Replace $dataStoreVersion with the version of data store which you use, e.g. 1.0.0:
implementation "androidx.datastore:datastore:$dataStoreVersion"
You can find the available versions here in Google's Maven repository.
After adding this dependency, you can use by dataStore by adding the following import to your class:
import androidx.datastore.dataStore
In Android documentation:
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
This line should be at the top of your code.
See DataStore documenation
After a lot of searching, The problem is simple. Make sure Gradle is not in offline mode.
Also, ensure that you use this dependency.
implementation "androidx.datastore:datastore-preferences:$dataStoreVersion"

How to get a FragmentManager for DialogFragment in Kotlin using Androidx?

I am following a tutorial where the instructor is using the Android support library v7. In my app I am using the androidx version (as suggested on the Android Developer website). When I type the lines of code as instructed, Android Studio puts a strikethrough over part of the code where I try to obtain a FragmentManager and says: "getter for fragmentManager: FragmentManager! is deprecated. Deprecated in Java." I have searched so many posts where people were having similar issues but the solutions provided don't apply to my case. Some users were having mismatched support library versions and others didn't have the proper dependencies in the gradle file. As far as I can tell those issues don't apply here.
According to the androidx documentation for FragmentManager, it states, "Your activity must derive from FragmentActivity to use this. From such an activity, you can acquire the FragmentManager by calling FragmentActivity#getSupportFragmentManager." However, I am not using an Activity, the code is inside an inner class that extends the RecylcerView.ViewHolder class which is nested inside a class extending RecyclerView.Adapter. Is my only choice to use the android support library v7?
RecyclerView Adapter Class:
import android.app.Activity
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.e_product_row.view.*
import androidx.fragment.app.DialogFragment // greyed out as "unused import directive"
import androidx.fragment.app.FragmentManager // greyed out as "unused import directive"
class EProductAdapter(var context: Context, var arrayList : ArrayList<EProduct>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val productView = LayoutInflater.from(context).inflate(R.layout.e_product_row, parent, false)
return ProductViewHolder(productView)
}
override fun getItemCount(): Int {
return arrayList.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
// downcast holder to ProductViewHolder
(holder as ProductViewHolder).initializeRowComponents(arrayList.get(position).id,
arrayList[position].name,
arrayList[position].price,
arrayList[position].picture)
}
inner class ProductViewHolder(productView: View) : RecyclerView.ViewHolder(productView) {
fun initializeRowComponents(id: Int, name: String, price: Int, pictureName: String) {
itemView.txt_id.text = id.toString()
itemView.txt_name.text = name
itemView.txt_price.text = price.toString()
var pictureUrl = "http://192.168.0.21/OnlineStoreApp/osimages/$pictureName"
pictureUrl = pictureUrl.replace(" ", "%20")
Picasso.get().load(pictureUrl).into(itemView.img_product)
// initialize add item imageView
itemView.img_add_item.setOnClickListener {
var amountFragment = AmountFragment()
var fragmentManager = (itemView.context as Activity).fragmentManager // fragmentManager strikethrough text
amountFragment.show(fragmentManager, "TAG") // show function cannot be called with arguments supplied and won't compile
}
}
}
}
DialogFragment class:
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
class AmountFragment : DialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? ): View? {
return inflater.inflate(R.layout.fragment_amount, container, false)
}
}
build.gradle(Module: app)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.bryontaylor.onlinestoreapp"
minSdkVersion 24
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.android.volley:volley:1.1.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.fragment:fragment:1.2.4'
implementation 'androidx.fragment:fragment-ktx:1.2.4'
}
According to the androidx documentation for FragmentManager, it
states, "Your activity must derive from FragmentActivity to use this.
From such an activity, you can acquire the FragmentManager by calling
FragmentActivity#getSupportFragmentManager." However, I am not using
an Activity
Yes you are:
var fragmentManager = (itemView.context as Activity).fragmentManager
The only problem is that you're casting to the root Activity type and using the deprecated getFragmentManager(). You need to do exactly as the docs state: use FragmentActivity and getSupportFragmentManager():
var fragmentManager = (itemView.context as FragmentActivity).supportFragmentManager
Your show() call will then work because you're passing in the correct fragment manager type.
Hope that helps!

Using lambda in custom BindingAdapter using Android Databinding and Kotlin

I'm trying to have a custom binding with a lambda handler for Android Databinding using Kotlin. It's working well as long as my ViewModel handler is explicitly returning Void. But if it returns Kotlin Unit instead, I get an error: cannot generate view binders java.lang.StackOverflowError.
Everything seems to be hooked-up correctly as all the other custom bindings works (convertBooleanToViewVisibility, toTestString and even customOnClick as long as I'm calling onClickVoid [see example below]).
The issue is when I'm trying to invoke a lambda returning Unit in my app:customOnClick instead of returning Void. In the example below, it's to invoke mainViewModel.onClick() instead of mainViewModel.onClickVoid(). There must be a way of making it work as the android:onClick is able to make to call to the Unit version. But if I'm using the same syntax for customOnClick calling onClick, I'm getting this error:
:app:kaptGenerateStubsDebugKotlin
Using kotlin incremental compilation
:app:kaptDebugKotlin
e: error: cannot generate view binders java.lang.StackOverflowError
e:
e: at android.databinding.tool.writer.Scope.access$getCurrentScope$cp(LayoutBinderWriter.kt:49)
e: at android.databinding.tool.writer.Scope$Companion.getCurrentScope(LayoutBinderWriter.kt:58)
e: at android.databinding.tool.writer.LayoutBinderWriterKt.scopedName(LayoutBinderWriter.kt:196)
e: at android.databinding.tool.expr.Expr.toCode(Expr.java:776)
e: at android.databinding.tool.writer.LayoutBinderWriterKt$callbackLocalName$2.invoke(LayoutBinderWriter.kt:203)
e: at android.databinding.tool.writer.LayoutBinderWriterKt$callbackLocalName$2.invoke(LayoutBinderWriter.kt)
e: at android.databinding.tool.ext.LazyExt.getValue(ext.kt:27)
e: at android.databinding.tool.writer.LayoutBinderWriterKt.getCallbackLocalName(LayoutBinderWriter.kt)
e: at android.databinding.tool.writer.LayoutBinderWriterKt.scopedName(LayoutBinderWriter.kt:197)
e: java.lang.IllegalStateException: failed to analyze: java.lang.RuntimeException: failure, see logs for details.
cannot generate view binders java.lang.StackOverflowError
at android.databinding.tool.writer.Scope.access$getCurrentScope$cp(LayoutBinderWriter.kt:49)
at android.databinding.tool.writer.Scope$Companion.getCurrentScope(LayoutBinderWriter.kt:58)
at android.databinding.tool.writer.LayoutBinderWriterKt.scopedName(LayoutBinderWriter.kt:196)
at android.databinding.tool.expr.Expr.toCode(Expr.java:776)
at android.databinding.tool.writer.LayoutBinderWriterKt$callbackLocalName$2.invoke(LayoutBinderWriter.kt:203)
at android.databinding.tool.writer.LayoutBinderWriterKt$callbackLocalName$2.invoke(LayoutBinderWriter.kt)
at android.databinding.tool.ext.LazyExt.getValue(ext.kt:27)
at android.databinding.tool.writer.LayoutBinderWriterKt.getCallbackLocalName(LayoutBinderWriter.kt)
at android.databinding.tool.writer.LayoutBinderWriterKt.scopedName(LayoutBinderWriter.kt:197)
.............................. (TRUNCATED) ...................................
at android.databinding.tool.expr.Expr.toCode(Expr.java:776)
at android.databinding.tool.writer.LayoutBinderWriterKt$callbackLocalName$2.invoke(LayoutBinderWriter.kt:203)
at android.databinding.tool.writer.LayoutBinderWriterKt$callbackLocalName$2.invoke(LayoutBinderWriter.kt)
at android.databinding.tool.ext.LazyExt.getValue(ext.kt:27)
at android.databinding.tool.writer.LayoutBinderWriterKt.getCallbackLocalName(LayoutBinderWriter.kt)
at android.databinding.tool.writer.LayoutBinderWriterKt.scopedName(LayoutBinderWriter.kt:197)
at org.jetbrains.kotlin.analyzer.AnalysisResult.throwIfError(AnalysisResult.kt:57)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules(KotlinToJVMBytecodeCompiler.kt:144)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:167)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:55)
at org.jetbrains.kotlin.cli.common.CLICompiler.exec(CLICompiler.java:182)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.execCompiler(CompileServiceImpl.kt:397)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.access$execCompiler(CompileServiceImpl.kt:99)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$2.invoke(CompileServiceImpl.kt:365)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$2.invoke(CompileServiceImpl.kt:99)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$2$$special$$inlined$withValidClientOrSessionProxy$lambda$1.invoke(CompileServiceImpl.kt:798)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$2$$special$$inlined$withValidClientOrSessionProxy$lambda$1.invoke(CompileServiceImpl.kt:99)
at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:137)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:825)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.access$checkedCompile(CompileServiceImpl.kt:99)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$2.invoke(CompileServiceImpl.kt:797)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$2.invoke(CompileServiceImpl.kt:99)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.ifAlive(CompileServiceImpl.kt:1004)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.ifAlive$default(CompileServiceImpl.kt:865)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.doCompile(CompileServiceImpl.kt:791)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.access$doCompile(CompileServiceImpl.kt:99)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1.invoke(CompileServiceImpl.kt:364)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1.invoke(CompileServiceImpl.kt:99)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.ifAlive(CompileServiceImpl.kt:1004)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.ifAlive$default(CompileServiceImpl.kt:865)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:336)
at sun.reflect.GeneratedMethodAccessor86.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:324)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
... 39 more
FAILED
Any idea how to make it work with Unit so I do not need to change my ViewModel to explicitly return Void? for all my handlers?
Sample project
Project build.gradle
buildscript {
ext.kotlin_version = '1.1.3-2'
ext.plugin_version = '2.3.3'
repositories {
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:$plugin_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Module (app) build.gradle
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
}
}
apply plugin: 'com.android.application'
apply plugin: "kotlin-android"
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 24
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.example.kotlindatabinding"
minSdkVersion 24
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
dataBinding {
enabled = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.+'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
kapt "com.android.databinding:compiler:$plugin_version"
}
kapt {
generateStubs = true
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
binding.setMainViewModel(MainViewModel())
}
}
MainViewModel.kt
class MainViewModel {
val myName: String
get() {
return "Hello world!"
}
fun onClick(){
Log.i("ME", "Logging...")
}
fun onClickVoid(): Void? {
onClick()
return null as Void?
}
}
Bindings.kt
object Bindings{
#BindingConversion
#JvmStatic fun convertBooleanToViewVisibility(isVisible: Boolean): Int {
// Working
return if (isVisible) View.VISIBLE else View.GONE
}
#BindingAdapter("customOnClick")
#JvmStatic fun setOnItemClicked(textView: TextView, consumer: (String) -> Any?) {
// Working
consumer("test")
}
#JvmStatic fun toTestString(input: Any) : String {
return "Test"
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.example.kotlindatabinding.Bindings"/>
<variable
name="mainViewModel"
type="com.example.kotlindatabinding.MainViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.kotlindatabinding.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{Bindings.toTestString(mainViewModel.myName)}"
android:visibility="#{mainViewModel.myName != null}"
android:clickable="true"
android:onClick="#{() -> mainViewModel.onClick()}"
app:customOnClick="#{(someInput) -> mainViewModel.onClickVoid()}" />
</LinearLayout>
</layout>
Well, very late response I suppose, but others might had the same issue:
As far as I see this is on a false assumption: databinding uses Java and doesn't know about Kotlin in general.
In order to set a listener via databinding you have to use a Java interface with a method. Kotlin lambdas are not like Java interfaces with a simple method since they contain functions, meaning they always return something (if not specified then Unit).
So to achieve setting a listener define a simple Java interface as a parameter in the binding adapter
Move this code outside the default config block. Put it inside
android {
dataBinding {
enabled = true
}
}