I am building a library module that using coroutines.
My library do the following:
get config from the app module
create a fragment that implemented CoroutineScope (ContentListingFragment)
ContentListingFragment handle all it's process fetching data from the network and show them
from the app module:
We should able to get an instance from the ContentListingFragment and add it to a container
The issue: when I am building the app, I am getting the following error:
Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
class nabed.apps.nabedutilslibrary.ui.base.ContentListingFragment, unresolved supertypes: kotlinx.coroutines.CoroutineScope
below is the library module build.gradle
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: "kotlin-kapt"
apply plugin: 'androidx.navigation.safeargs'
android {
compileSdkVersion 28
buildToolsVersion "29.0.0"
defaultConfig {
minSdkVersion 21
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
jvmTarget = "1.8"
}
}
}
androidExtensions{
experimental = true
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
// Navigation
implementation "android.arch.navigation:navigation-fragment:$navigation_version"
implementation "android.arch.navigation:navigation-ui:$navigation_version"
implementation "android.arch.navigation:navigation-fragment-ktx:$navigation_version"
implementation "android.arch.navigation:navigation-ui-ktx:$navigation_version"
//Kotlin Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0-RC1"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
How to handle this without changes on the app module?
You have to change the dependencies declaration in your library's build.gradle:
//Kotlin Coroutines
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0"
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0-RC1"
api keyword will expose these dependencies to the app module
****put this code in build.gradel file in dependencies block and click on sync****
//Kotlin Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0"
If you are not going to use Coroutines in the app module but would like to use it in the library, decision with api dependencies not the best one. In this way your app module will be also dependent on Coroutines.
I think, better to remove CoroutineScope implementation from ContentListingFragment and create CoroutineScope object as a ContentListingFragment member.
class ContentListingFragment : Fragment() {
private val job = Job()
private val coroutineScope = object : CoroutineScope {
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.IO
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
coroutineScope.launch { ... }
}
override fun onDestroyView() {
super.onDestroy()
job.cancelChildren()
}
}
Also, LifecycleScope form lifecycle-runtime-ktx may be a the easiest solution. It will remove CoroutineScope creation boilerplate code.
class ContentListingFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch { ... }
}
}
Related
I have spent the hole week trying to add hilt dependency injection to my sample note application, android studio have been throwing on me error after an error.It got me mad, any way, in AppModule i have been trying to inject my room database to app repository and then my app repo to my use cases class and at the end injecting use cases class to my sharedViewModel
so this is my AppModule object:
#Module
#InstallIn(SingletonComponent::class)
object AppModule {
#Provides
#Singleton
fun provideNoteDatabase(app: Application): NoteDatabase {
return Room.databaseBuilder(
app,
NoteDatabase::class.java,
NoteDatabase.DATABASE_NAME
).build()
}
#Provides
#Singleton
fun provideNoteRepository(db: NoteDatabase): NotesRepo {
return RepoImplementation(db.noteDao())
}
#Provides
#Singleton
fun provideNoteUseCase(repo: NotesRepo): NoteUseCase {
return NoteUseCase(
getNotesUseCase = GetNotesUseCase(repo),
deleteNoteUseCase = DeleteNoteUseCase(repo),
updateNoteUseCase = UpdateNoteUseCase(repo),
insertNoteUseCase = InsertNoteUseCase(repo)
)
}
}
and this my Application class:
#HiltAndroidApp
class Application : Application()
my edit fragment:
#AndroidEntryPoint
class EditFragment : Fragment() {
private var _binding: FragmentEditBinding? = null
private val binding get() = _binding!!
private val viewModel: SharedViewModel by activityViewModels()
//...
}
my other fragment:
#AndroidEntryPoint
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
private val viewModel: SharedViewModel by activityViewModels()
//...
}
by the way also my MainActivity is annotated with #AndroidEntryPoint
my famous viewModel :
#HiltViewModel
class SharedViewModel #Inject constructor(private val noteUseCase: NoteUseCase) :
ViewModel() {...}
this is project level build.gradle:
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
def nav_version = "2.5.2"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.44'
}
}
plugins {
id 'com.android.application' version '7.3.0' apply false
id 'com.android.library' version '7.3.0' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}
and module level build.gradle:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android'
id 'kotlin-kapt'
id "androidx.navigation.safeargs"
id 'com.google.dagger.hilt.android'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.stayin"
minSdk 21
targetSdk 32
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'
}
buildFeatures {
dataBinding true
viewBinding true
}
namespace 'com.example.stayin'
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
def lifecycle_version = "2.4.1"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// coroutines for getting off the UI thread
def coroutines = "1.6.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
//shared preferences dependency
implementation 'androidx.preference:preference-ktx:1.2.0'
// Room dependency
def room_version = "2.4.3"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
//navigation component dependency
implementation "androidx.navigation:navigation-fragment-ktx:2.5.2"
implementation "androidx.navigation:navigation-ui-ktx:2.5.2"
//Dagger - Hilt
implementation 'com.google.dagger:hilt-android:2.44'
kapt 'com.google.dagger:hilt-compiler:2.44'
// For instrumentation tests
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.44'
kaptAndroidTest 'com.google.dagger:hilt-compiler:2.44'
// For local unit tests
testImplementation 'com.google.dagger:hilt-android-testing:2.44'
kaptTest 'com.google.dagger:hilt-compiler:2.44'
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
}
if can any one help me to find what is wrong and explained why, i will be so thankful towards him. i rally need to pass this so i can level up in my career.
Remove below deprecated dependency:
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
(It was deprecated since dagger-2.34 version)
proof:
https://github.com/google/dagger/releases/tag/dagger-2.34
Also Try to upgrade your lifecycle version as below:
def lifecycle_version = "2.5.1"
add below lines after dependency section in build.gradle(app):
kapt { correctErrorTypes true }
follow official documentation:
https://developer.android.com/training/dependency-injection/hilt-android
https://dagger.dev/hilt/view-model.html
I took the Udacity course to learn developing Android apps with Kotlin, using data binding multiple times during it and having no problems enabling it, but now, trying to set up my first project, I am having some problems with it: Android Studio doesn't find the reference to the MainActivityBinding.
C:\Dev\Projects\Android_Studio\myproject\app\src\main\java\com\guglielmoboi\myproject\MainActivity.kt: (8, 35): Unresolved reference: MainActivityBinding
These are the files I produced:
build.gradle (project)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
kotlin_version = "1.4.32"
}
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.3"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
build.gradle (:app)
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.guglielmoboi.myproject"
minSdkVersion 26
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'
}
}
**buildFeatures {
dataBinding true
viewBinding true
}**
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
/* Room dependencies */
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
// optional - Test helpers
testImplementation "androidx.room:room-testing:$room_version"
/* Navigation dependencies */
def nav_version = "2.3.5"
// Java language implementation
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
// Feature module Support
implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
// Testing Navigation
androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"
// Jetpack Compose Integration
implementation "androidx.navigation:navigation-compose:1.0.0-alpha10"
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.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
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>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
MainActivity.kt
package com.guglielmoboi.myproject
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity()
{
private lateinit var binding: MainActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Inside MainActivity
remove setContentView(R.layout.activity_main)
and add
val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
Use binding for all the UI stuff.
I want to inject dependencies in android tests using dagger.
I've created a simple App with an AppComponent extending AndroidInjector.
That works for the App itself (the code is built in /build by dagger).
Then, for /test I've also created the AppComponentTest and AppTest.
It took me some time to realised that I need to create a naive test and run it to let gradle create the /build for test.
Now the code is there, but there is some error with that generated code, as you can see here:
AppComponent.kt
#Singleton
#Component(
modules = [
AndroidSupportInjectionModule::class
]
)
interface AppComponent : AndroidInjector<App> {
#Component.Factory
interface Factory {
fun create(#BindsInstance application: Application): AppComponent
}
}
App.kt
open class App : Application(), HasAndroidInjector {
#Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
override fun androidInjector(): AndroidInjector<Any> = dispatchingAndroidInjector
override fun onCreate() {
super.onCreate()
setupDagger()
}
#VisibleForTesting
open fun setupDagger() {
DaggerAppComponent
.factory()
.create(this)
.inject(this)
}
}
Then under the same structure but in /test I've created this:
AppComponentTest.kt
#Singleton
#Component(
modules = [
AndroidSupportInjectionModule::class
]
)
interface AppComponentTest : AppComponent {
#Component.Factory
interface Factory {
fun create(
#BindsInstance application: Application
): AppComponentTest
}
}
AppTest.kt
class AppTest : App() {
override fun setupDagger() {
DaggerTestAppComponent
.factory()
.create(this)
.inject(this)
}
}
And this is the build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.example.dagger"
minSdkVersion 21
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'
}
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
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'
def dagger_version = "2.27"
implementation "com.google.dagger:dagger-android:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version"
kapt "com.google.dagger:dagger-android-processor:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"
testImplementation 'junit:junit:4.13'
kaptTest "com.google.dagger:dagger-compiler:$dagger_version"
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
Also the naive test:
ExampleUnitTest.kt
#RunWith(JUnit4::class)
class ExampleUnitTest {
#Test
fun test() {
assert(true)
}
}
I've also tried with other approach using this:
AppComponentTest2.kt
#Singleton
#Component(modules = [])
interface AppComponentTest2 {
fun inject(test: ExampleUnitTest2)
}
ExampleUnitTest2.kt
#RunWith(JUnit4::class)
class ExampleUnitTest2 {
#Test
fun test() {
DaggerAppComponentTest2
.builder()
.build()
.inject(this)
assert(true)
}
}
And also the same error:
Btw, this is a repo with that code:
https://gitlab.com/fitu/dagger
There are two branches there first_approach and second_approach
EDIT 1:
I had other repo where I was able to do this injection and now I've tried and it doesn't work.
Comparing dependencies I have:
New project:
classpath 'com.android.tools.build:gradle:3.6.1'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61'
implementation 'com.google.dagger:dagger-android:2.27'
implementation 'com.google.dagger:dagger-android-support:2.27'
kapt 'com.google.dagger:dagger-android-processor:2.27'
kapt 'com.google.dagger:dagger-compiler:2.27'
kaptTest 'com.google.dagger:dagger-compiler:2.27'
Old project:
classpath 'com.android.tools.build:gradle:3.2.0'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.70'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.61'
implementation'com.google.dagger:dagger-android-support:2.14.1'
kapt 'com.google.dagger:dagger-compiler:2.14.1'
kaptTest 'com.google.dagger:dagger-compiler:2.14.1'
So it seems is not a dagger or kotlin version.
Maybe it's related with Android Studio?
I'm not sure about the version of AS when I'd created that old project, but my current AS version is: 3.6.1
EDIT 2:
I've deleted almost everything in the project, the main folder with App and everything:
The only reminding was two classes: AppComponentTest.kt and ExampleUnitTest.kt
#Singleton
#Component(modules = [])
interface AppComponentTest
class ExampleUnitTest {
#Test
fun test() {
DaggerAppComponentTest
.builder()
.build()
assert(true)
}
}
The error persist, so I'm guessing the problem could be a combinations of AS version, Kotlin version and/or Dagger version.
I am trying to communicate with viewmodel from xml and vice versa using MVVM pattern. I have worked on databinding before and successfully worked with Live Data - Dagger - MVVM .
Recently, I have tried to create a new project and since then I cannot track the response with XML and viewmodel. Neither the onClick from XML -> ViewModel nor the assigning value to the textview from View -> XML is working. But there is no crash or anything, just it is not working. I have added all associated files [ MainActivity, activity_main, viewModel, Dagger Module, build.gradle ]
I will really appreciate if anyone can tell me what is going wrong here.
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>
<variable
name="viewmodel"
type="aveek.com.vm.ui.home.MainActivityViewModel"/>
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{viewmodel.balanceText}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:clickable="true"
android:onClick="#{() -> viewmodel.clickData()}"
app:layout_constraintTop_toTopOf="parent" />
...
</layout>
MainActivity.kt
class MainActivity : AppCompatActivity(),LifecycleOwner {
#Inject
lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding.setLifecycleOwner(this)
with(binding){
this.viewmodel?.let {
it.balanceText.set( "Aveek testing")
it.data.observe(this#MainActivity, Observer {
Toast.makeText(this#MainActivity, "Data is now : $it", Toast.LENGTH_SHORT).show()
})
}
}
}
MainActivityViewModel.kt
class MainActivityViewModel : ViewModel() {
val data = MutableLiveData<Boolean>()
val balanceText = ObservableField<String>()
fun clickData(){
data.value = false
}
}
MainActivityModule.kt
#Module
class MainActivityModule{
/**
* provides binding to Main Activity from respective XML
* #property viewModel
* #property context
* #return binding of the view
*/
#Provides
fun binding(context: MainActivity, viewModel : MainActivityViewModel) :
ActivityMainBinding {
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(context,
R.layout.activity_main)
binding.viewmodel = viewModel
return binding
}
}
build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 27
defaultConfig {
applicationId "aveek.test"
minSdkVersion 15
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
dataBinding {
enabled = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
kapt {
generateStubs = true
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:multidex:1.0.2'
implementation 'com.android.support:design:27.1.1'
implementation "android.arch.lifecycle:extensions:1.1.0"
// annotationProcessor "android.arch.lifecycle:compiler:1.1.0"
kapt "com.android.databinding:compiler:$androidPluginVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
annotationProcessor "com.google.dagger:dagger-android-processor:$daggerVersion"
kapt "com.google.dagger:dagger-compiler:$daggerVersion"
kapt "com.google.dagger:dagger-android-processor:$daggerVersion"
implementation "com.google.dagger:dagger:$daggerVersion"
implementation "com.google.dagger:dagger-android:$daggerVersion"
implementation "com.google.dagger:dagger-android-support:$daggerVersion"
kapt "com.google.dagger:dagger-compiler:$daggerVersion"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-
core:3.0.2'
}
ext{
kotlin_version = '1.2.31'
androidPluginVersion = '3.1.0'
daggerVersion = '2.13'
}
you won't be able to use any generated methods to set your variable to the binding, as there's no common superclass besides the ViewDataBinding,so you will be forced to use reflection, or you can use the convenience method setVariable():
binding.setVariable(BR.viewModel, viewModel);
As I suspected, the problem is with Dagger injection. Maybe I have implemented in a wrong approach but the viewmodel is perfectly fine if running without DI.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProviders.of(this).get(MainActivityViewModel::class.java)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.viewmodel = viewModel
binding.setLifecycleOwner(this)
mLifecycleRegistry = LifecycleRegistry(this).apply {
markState(Lifecycle.State.CREATED)
}
with(binding){
this.viewmodel?.let {
it.balanceText.set( "Aveek testing")
it.data.observe(this#MainActivity, Observer {
Toast.makeText(this#MainActivity, "Data is now : $it",
Toast.LENGTH_SHORT).show()
})
}
}
}
So, I have gone through the DI code and found out that in MainActivity.onCreate()
I was doing this
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
which basically overriding the databinding behaviour. So I have updated the code like this
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
//setContentView(R.layout.activity_main)
// and initiated binding here as injecting binding from module before setting content won't be effective
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
And removed
// #Inject
// lateinit var binding : ActivityMainBinding
Now it works perfectly fine..
Data binding setup:
apply plugin: 'kotlin-kapt'
android {
dataBinding {
enabled = true
}
}
dependencies {
kapt "com.android.databinding:compiler:3.1.0"
}
The fragment class which uses data binding:
class LandingFragment : Fragment(), Injectable {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val dataBinding = LandingFragmentBinding.inflate(inflater, container, false)
return dataBinding.root
}
}
Every time the Espresso test is run for this fragment, I get the following exception:
java.lang.NoClassDefFoundError: android.databinding.DataBinderMapperImpl
at android.databinding.DataBindingUtil.<clinit>(DataBindingUtil.java:32)
at com.sc.databinding.LandingFragmentBinding.inflate(LandingFragmentBinding.java:42)
at com.sc.ui.landing.LandingFragment.onCreateView(LandingFragment.kt:32)
...
A bit late, but I resolved this issue by adding DataBinding compiler with kapt as a test dependency:
kaptAndroidTest 'androidx.databinding:databinding-compiler:3.3.2'
Or the version not from AndroidX if your project is not using Jetpack yet.
Add
kaptTest "androidx.databinding:databinding-compiler:+"
to dependencies on build.gradle files of all your modules.
I run into this very error. I did 2 things:
1. Added kaptAndroidTest 'androidx.databinding:databinding-compiler:3.5.1' in gradle
2. Used the databinding, that is to say, I create a fake bool variable and injected it for real in a view. It would seem that you cannot just use databinding for retrieving the views instead of issuing the dreaded findViewById. You have to use it at least once in your module. Once you use it you are fine for all the other classes in your module.
I have the same this issue, and fixed by adding
kapt {
generateStubs = true
}
in build.gradle app (all module if using dataBinding)
apply plugin: 'kotlin-kapt'
android {
...
dataBinding {
enabled = true
}
}
kapt {
generateStubs = true
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
...
implementation "androidx.core:core-ktx:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
kapt "com.android.databinding:compiler:$android_plugin_version"
}
In build.gradle project
buildscript {
ext.kotlin_version = '1.3.70'
ext.android_plugin_version = '3.5.2'
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:$android_plugin_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Add dataBinding = true to android { } in your build.gradle file, and everything will be fine, hope this help..
build.gradle:
android {
// skip ..
buildFeatures {
//noinspection DataBindingWithoutKapt
dataBinding = true
viewBinding true
}
// skip ..
}
Try to add the android-apt plugin as per this stackoverflow answer:
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'