- 基本概念
控制反转(Inversion of Control,英文缩写为 IoC):创建被调用者的工作不再由调用者来完成,因此称为控制反转。
依赖注入(Dependency Injection,简称DI):控制反转的主要实现方式,可以通过反射方式实现(ViewUtils,反射注入),也可以非反射方式(Dagger2)
ORM:即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作对象的属性和方法。(ORMLite,DBUtils,greendao)
- Dagger2:
1.介绍:
依赖注入就是将调用者需要的另一个对象实例不在调用者内部实现,而是通过一定的方式从外部传入实例,解决了各个类之间的耦合。
那么这个外部,到底指的是哪里,如果指的是另一个类,那么,另一个类内部不就耦合了。能不能有一种方式,将这些构造的对象放到一个容器中,具体需要哪个实例时,就从这个容器中取就行了。那么,类的实例和使用就不在有联系了,而是通过一个容器将他们联系起来。实现了解耦。这个容器,便是
Dagger2
。
Dagger2
是Google出的依赖注入框架。肯定有小伙伴疑问,为什么会有个 2 呢。该框架是基于square
开发的dagger
基础上开发的。
Dagger2
的原理是在编译期生成相应的依赖注入代码。这也是和其他依赖注入框架不同的地方,其他框架是在运行时期反射获取注解内容,影响了运行效率。2.导入Dagger2:
在工程的
build.gradle
文件中添加android-apt
插件:dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
// 添加android-apt 插件
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
app的build.gradle:
apply plugin: 'com.android.application'
// 应用插件
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 23
buildToolsVersion "24.0.1"
defaultConfig {
applicationId "com.qf.zhouyi.daggertest"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
warning 'InvalidPackage'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
// dagger 2 的配置
compile 'com.google.dagger:dagger:2.4'
apt 'com.google.dagger:dagger-compiler:2.4'
compile 'org.glassfish:javax.annotation:10.0-b28'
// 添加java 注解库
compile 'com.google.code.gson:gson:2.7'
}
android-apt
是Gradle
编译器的插件,根据其官方文档,主要两个目的:
编译时使用该工具,最终打包时不会将该插件打入到apk中。
能够根据设置的源路径,在编译时期生成相应代码。
dagger
是主要的工具类库。dagger-compiler
为编译时期生成代码等相关的类库。在
android-apt
的文档中,也推荐使用这种方式。因为,编译时期生成代码的类库在运行期并不需要,那么将其分为两个库,(运行类库dagger
)和(编译器生成代码类库(dagger-compiler
)),那么在打包时,就不需要将dagger-compiler
打入其中(用不到),减小APK 的大小。
3.使用
Dagger2
将程序分为三个部分。
- 实例化部分:对象的实例化。类似于容器,将类的实例放在容器里。
- 调用者:需要实例化对象的类。
- 沟通桥梁:利用Dagger2
中的一些API 将两者联系。
实例化部分:Module
package com.qf.zhouyi.daggerdemo;
import android.util.Log;
public class Person {
public void doSomething(){
Log.e("qf", "do something");
}
}
package com.qf.zhouyi.daggerdemo;
import dagger.Module;
import dagger.Provides;
/**
* Created by zhouyi on 16/8/22.
*/
@Module
public class PersonModule {
@Provides
Person providePerson(){
return new Person();
}
}
沟通部分Component
package com.qf.zhouyi.daggerdemo;
import dagger.Component;
/**
* Created by zhouyi on 16/8/22.
*/
@Component(modules = {PersonModule.class})
public interface PersonComponent {
void inject(MainActivity mainActivity);
}
一个Component可以沟通多个module:
package com.qf.zhouyi.daggerdemo;
import dagger.Component;
/**
* Created by zhouyi on 16/8/22.
*/
@Component(modules = {PersonModule.class,GsonModule.class})
public interface PersonComponent {
void inject(MainActivity mainActivity);
}
package com.qf.zhouyi.daggerdemo;
import com.google.gson.Gson;
import dagger.Module;
import dagger.Provides;
/**
* Created by zhouyi on 16/8/22.
*/
@Module
public class GsonModule {
@Provides
Gson provideGosn(){
return new Gson();
}
}
package com.qf.zhouyi.daggerdemo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.google.gson.Gson;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
Person person;
@Inject
Gson gson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerPersonComponent.builder().build().inject(this);
person.doSomething();
String strJson = "{\n" +
" NAME:\"Albert Attard\",\n" +
" P_LANGUAGE:\"Java\",\n" +
" LOCATION:\"Malta\"\n" +
"}\n";
MyData myData = gson.fromJson(strJson,MyData.class);
Log.d("qf",myData.toString());
}
}
@Singleton 单例注解
假如,对于同一个对象,我们需要注入两次,如下方式:
package com.qf.zhouyi.daggerdemo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.google.gson.Gson;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
Person person;
@Inject
Person person2;
@Inject
Gson gson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerPersonComponent.builder().build().inject(this);
//person.doSomething();
Log.i("dagger","person = "+ person.toString()+"; person2 = "+ person2.toString());
}
}
打印出来的对象地址是不一样的
如果要使用单例,需要在module和component里加入singleton注解
@Component(modules = {PersonModule.class})
@Singleton
public interface PersonComponent {
void inject(MainActivity mainActivity);
}
package com.qf.zhouyi.daggerdemo;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
/**
* Created by zhouyi on 16/8/22.
*/
@Module
public class PersonModule {
@Provides
@Singleton
Person providePerson(){
return new Person();
}
}
但是,如果是不同的component,就无法保持单例:
package com.qf.zhouyi.daggerdemo;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
Person person;
@Inject
Person person2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerPersonComponent.builder().build().inject(this);
//person.doSomething();
Log.i("dagger","person = "+ person.toString()+"; person2 = "+ person2.toString());
}
public void onShow(View view) {
Intent intent = new Intent();
intent.setClass(this,MainActivity2.class);
startActivity(intent);
}
}
package com.qf.zhouyi.daggerdemo;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import javax.inject.Inject;
/**
* Created by zhouyi on 16/8/22.
*/
public class MainActivity2 extends AppCompatActivity {
@Inject
Person person3;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
DaggerPersonComponent.builder().build().inject(this);
//person.doSomething();
Log.i("dagger","person3 = "+ person3.toString());
}
}
package com.qf.zhouyi.daggerdemo;
import javax.inject.Singleton;
import dagger.Component;
/**
* Created by zhouyi on 16/8/22.
*/
@Component(modules = {PersonModule.class})
@Singleton
public interface PersonComponent {
void inject(MainActivity mainActivity);
void inject(MainActivity2 mainActivity2);
}
思考:如何得到全局的单例
带参数实例化
package com.qf.zhouyi.daggerdemo;
import android.util.Log;
public class Person {
int aa;
public Person(int a){
aa = a;
}
public void doSomething(){
Log.e("qf", "do something " + aa);
}
}
package com.qf.zhouyi.daggerdemo;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
/**
* Created by zhouyi on 16/8/22.
*/
@Module
public class PersonModule {
int aa;
PersonModule(int a){
aa = a;
}
@Provides
@Singleton
Person providePerson(){
return new Person(aa);
}
}
调用:
DaggerPersonComponent
.builder()
.personModule(new PersonModule(4))
.build()
.inject(this);
person.doSomething();
一个创建依赖另一个创建:
package com.qf.zhouyi.daggerdemo;
import dagger.Module;
import dagger.Provides;
/**
* Created by zhouyi on 16/8/22.
*/
@Module
public class IntModule {
@Provides
int providesInt(){
return 5;
}
}
package com.qf.zhouyi.daggerdemo;
import dagger.Component;
/**
* Created by zhouyi on 16/8/22.
*/
@Component(modules = IntModule.class)
public interface IntComponent {
int provideInt();
}
package com.qf.zhouyi.daggerdemo;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
/**
* Created by zhouyi on 16/8/22.
*/
@Module
public class PersonModule {
// int aa;
//
// PersonModule(int a){
// aa = a;
// }
@Provides
@Singleton
Person providePerson(int a){
return new Person(a);
}
}
package com.qf.zhouyi.daggerdemo;
import javax.inject.Singleton;
import dagger.Component;
/**
* Created by zhouyi on 16/8/22.
*/
@Component(modules = {PersonModule.class},dependencies = IntComponent.class)
@Singleton
public interface PersonComponent {
void inject(MainActivity mainActivity);
void inject(MainActivity2 mainActivity2);
}
调用:
IntComponent intComponent = DaggerIntComponent.builder().build();
DaggerPersonComponent.builder()
.intComponent(intComponent)
.personModule(new PersonModule())
.build().inject(this);
person.doSomething();
多个不同的构造方法:
package com.qf.zhouyi.daggerdemo;
import android.util.Log;
public class Person {
int aa;
String mstrMsg;
public Person(int a){
aa = a;
}
public Person(String strMsg){
mstrMsg = strMsg;
}
public void doSomething2(){
Log.e("qf","do something2"+mstrMsg);
}
public void doSomething(){
Log.e("qf", "do something " + aa);
}
}
在上例的基础上,增加stringmodule,stringcomponent:
package com.qf.zhouyi.daggerdemo;
import dagger.Component;
/**
* Created by zhouyi on 16/8/22.
*/
@Component(modules = StringModule.class)
public interface StringComponent {
String provideString();
}
package com.qf.zhouyi.daggerdemo;
import dagger.Module;
import dagger.Provides;
/**
* Created by zhouyi on 16/8/22.
*/
@Module
public class StringModule {
@Provides
String providesString(){
return "abc";
}
}
personcomponet:
package com.qf.zhouyi.daggerdemo;
import javax.inject.Singleton;
import dagger.Component;
/**
* Created by zhouyi on 16/8/22.
*/
@Component(modules = {PersonModule.class},dependencies = {IntComponent.class,StringComponent.class})
@Singleton
public interface PersonComponent {
void inject(MainActivity mainActivity);
//void inject(MainActivity2 mainActivity2);
}
personmodule:
package com.qf.zhouyi.daggerdemo;
import javax.inject.Named;
import dagger.Module;
import dagger.Provides;
/**
* Created by zhouyi on 16/8/22.
*/
@Module
public class PersonModule {
// int aa;
// String mstrMsg;
//
// PersonModule(int a){
// aa = a;
// }
//
// PersonModule(String strMsg){
// mstrMsg = strMsg;
// }
@Named("int")
@Provides
Person providePerson(int a){
return new Person(a);
}
@Named("string")
@Provides
Person providePerson2(String strMsg){
return new Person(strMsg);
}
}
调用:
IntComponent intComponent = DaggerIntComponent.builder().build();
StringComponent stringComponent = DaggerStringComponent.builder().build();
DaggerPersonComponent.builder()
.intComponent(intComponent)
.stringComponent(stringComponent)
.personModule(new PersonModule())
.build().inject(this);
person.doSomething();
person2.doSomething2();
可以使用两个自定义注解替换前面的name注解:
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface PersonInt {
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface PersonString {
}
懒加载Lazy和强制重新加载Provider
@PersonInt
@Inject
Lazy<Person> person;
Person p = person.get();
Log.i("dagger","person = "+ p.toString());
Person p2 = person.get();
Log.i("dagger","person2 = "+ p2.toString());
上面打印出来地址一样
改成:
@PersonInt
@Inject
Provider<Person> person;
打印地址不一样