Kotlin+Dagger2开发android应用需要注意的那些问题

Kotlin已经出来很久了,最近也开始用kotlin开发android应用了,但是在使用kotlin+dagger2开发android应用的时候遇到了一些问题,在这里记录一下,希望能帮到同样遇到这些问题的同学。

先看一下在java下一个简单的dagger2的例子。
1、在app的build.gradle里加入dagger2的库

1
2
compile 'com.google.dagger:dagger:2.15'
annotationProcessor 'com.google.dagger:dagger-compiler:2.15'

2、编写一个简单的AppModule和AppComponent

1
2
3
4
5
6
7
8
@Module
public class AppModule {

@Provides
public String provideHelloWorld(){
return "Hello World";
}
}
1
2
3
4
5
@Component(modules = AppModule.class)
public interface AppComponent {

void inject(MainActivity activity);
}

3、在MainActivity里使用

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MainActivity extends AppCompatActivity {

@Inject
String helloWorld;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerAppComponent.create().inject(this);
Toast.makeText(this, helloWorld, Toast.LENGTH_SHORT).show();
}
}

OK,到此一个用java写的简单的dagger2的例子就到此结束了,运行一切正常。
然后我们将这个例子搬到kotlin下看看效果
1、同样在build.gradle里加入dagger2的引用,跟上面一样这里就不多写了
2、编写一个同样的AppModule和AppComponent

1
2
3
4
5
6
7
8
@Module
class AppModule {

@Provides
fun provideHelloWorld():String{
return "Hello World"
}
}
1
2
3
4
@Component(modules = [AppModule::class])
interface AppComponent {
fun inject(mainActivity: MainActivity)
}

上面两步都没有问题,跟java一样只是换成了用Kotlin来写。但是接下来使用DaggerAappComponent的使用就出问题了,我们知道DaggerAappComponent是dagger根据我们AppComponent类生成的,但是现在DaggerAappComponent这个类并没有生成。

尝试了很多办法各种make、build clean、重启Android Studio、修改Kotlin版本、修改Dagger2版本等等,发现都没有效果,后来才发现原来使用Kotlin的build.gradle的配置不一样,要使用kotlin-kapt插件,要将annotationProcessor换成kapt。如下

1、在app的build.gradle加上kotlin-kapt的插件

1
apply plugin: 'kotlin-kapt'

2、dependencies中dagger2的引用改为

1
2
implementation 'com.google.dagger:dagger:2.15'
kapt 'com.google.dagger:dagger-compiler:2.15'

然后重新编译项目,终于生成了DaggerAappComponent了,然后在MainActivity中使用

1
2
3
4
5
6
7
8
9
10
11
12
class MainActivity : AppCompatActivity() {

@Inject
var helloWorld:String? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
DaggerAppComponent.create().inject(this)
Toast.makeText(this, helloWorld, Toast.LENGTH_SHORT).show()
}
}

运行。。。然后报错了

1
2
3
4
5
6
7
8
Error:(10, 2) 错误: Dagger does not support injection into private fields
private java.lang.String helloWorld;
^
Error:(13, 2) 错误: com.cm.kotlindagger2demo.MainActivity cannot be provided without an @Inject constructor or from an @Provides-annotated method.
public abstract void inject(@org.jetbrains.annotations.NotNull()
^
com.cm.kotlindagger2demo.MainActivity is injected at
com.cm.kotlindagger2demo.AppComponent.inject(mainActivity)

原来使用dagger2注入时变量要使用关键字lateinit修饰,顾名思义就是延迟初始化的意思,修改如下:

1
2
@Inject
lateinit var helloWorld:String

运行,终于正常了。打完收工!

坚持原创技术分享,您的支持将鼓励我继续创作!