0
点赞
收藏
分享

微信扫一扫

Dagger2 入门

小迁不秃头 2021-09-30 阅读 43
Android

1.Dagger2的简单使用

为什么需要使用Dagger2?
通过Dagger2的目的是将程序分为三个部分。

  • 实例化部分:对象的实例化。类似于容器,将类的实例放在容器中
  • 调用者:需要实例化对象的类
  • 沟通桥梁:利用Dagger2中的一些API将两者联系。

1.1.实例化部分(容器),在此处是Module

@Module   //提供依赖对象的实例
public class MainModule {

    @Provides // 关键字,标明该方法提供依赖对象
    Person providerPerson(){
        //提供Person对象
        return new Person();
    }


}

1.2 沟通部分Component

@Component(modules = MainModule.class)  // 作为桥梁,沟通调用者和依赖对象库
public interface MainComponent {

    //定义注入的方法
    void inject(MainActivity activity);

}

1.3 使用者Activity中调用

public class MainActivity extends AppCompatActivity{

    @Inject   //标明需要注入的对象
    Person person;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 构造桥梁对象
        MainComponent component = DaggerMainComponent.builder().mainModule(new MainModule()).build();

        //注入
        component.inject(this);

    }
}

看一下Person


public class Person {

    public Person(){
        Log.i("dagger","person create!!!");
    }


}

我们来分析下调用过程:

  • 创建Component(桥梁),并调用注入方法。
// 构造桥梁对象
        MainComponent component = DaggerMainComponent.builder().mainModule(new MainModule()).build();

        //注入
        component.inject(this);

  • 查找当前类中带有@Inject的成员变量。
@Inject   //标明需要注入的对象
    Person person;
  • 根据成员变量的类型从Moudle中查找哪个有@Providers注解的方法返回值为当前类型。
 @Provides // 关键字,标明该方法提供依赖对象
    Person providerPerson(){
        //提供Person对象
        return new Person();
    }

在使用过程出现了很多注解:

  • @Module:作为实例对象的容器。
  • @Provides:标注能够提供实例化对象的方法。
  • @Component:作为桥梁,注入对象的通道。
  • @Inject:需要注入的方法

2. @Singleton 单例注解

假如,对于同一个对象,我们需要注入两次,如下方式:

public class MainActivity extends AppCompatActivity{

    @Inject
    Person person;

    @Inject
    Person person2;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 构造桥梁对象
        MainComponent component = DaggerMainComponent.builder().mainModule(new MainModule()).build();

        //注入
        component.inject(this);

        // 打印两个对象的地址
        Log.i("dagger","person = "+ person.toString()+"; person2 = "+ person2.toString());
    }
}

看一下结果:

person = com.mahao.alex.architecture.dagger2.Person@430d1620;
person2 = com.mahao.alex.architecture.dagger2.Person@430d17c8

可见两个对象不一致。也就是说创建了两个对象。
可以在提供实例化对象的方法上添加@Singleton注解

@Provides // 关键字,标明该方法提供依赖对象
    @Singleton
    Person providerPerson(){

        return new Person();
    }

同时,对于MainComponent也需要添加注解,不添加则会无法编译

@Singleton
@Component(modules = MainModule.class)  // 作为桥梁,沟通调用者和依赖对象库
public interface MainComponent {
    //定义注入的方法
    void inject(MainActivity activity);

}

此时在Log,会发现两个对象的地址一样,可见是同一个对象。

那么不同的Activity之间,能否保持单例呢?

创建一个新的Activity,代码如下:

public class Main2Actvity extends AppCompatActivity {

    @Inject
    Person person;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 构造桥梁对象
        MainComponent component = DaggerMainComponent.builder().mainModule(new MainModule()).build();

        //注入
        component.inject(this);

        Log.i("dagger","person = "+ person.toString());
    }
}

结果如下:

person create!!!
 person = com.mahao.alex.architecture.dagger2.Person@4310f898; person2 = com.mahao.alex.architecture.dagger2.Person@4310f898
 person create!!!
 person = com.mahao.alex.architecture.dagger2.Person@43130058

可见,@Singleton只对一个Component有效,即其单例所依赖Component对象.

3.需要参数的实例化对象

Person的构造方法发生了变化,需要传入一个Context,代码如下:

public class Person {

    private Context mContext;

    public Person(Context context){
        mContext = context;
        Log.i("dagger","create");
    }

}

这样的话,我们需要修改MainModule

@Module   //提供依赖对象的实例
public class MainModule {

    private Context mContext;

    public MainModule(Context context){
        mContext = context;
    }


    @Provides
    Context providesContext(){
        // 提供上下文对象
        return mContext;
    }

    @Provides // 关键字,标明该方法提供依赖对象
    @Singleton
    Person providerPerson(Context context){

        return new Person(context);
    }

}
  • 修改providerPerson方法,传入Context 对象。
  • 添加providesContext(),用以提供Context对象。

看一下使用

// 构造桥梁对象
        MainComponent component = DaggerMainComponent.builder().mainModule(new MainModule(this)).build();

        //注入
        component.inject(this);

逻辑:

  • 根据@Inject注解,查找需要依赖注入的对象。
  • MainModule中根据返回值,找到providerPerson(Context context) 对象。
  • 发现其需要传入参数 Context,找到module中具有返回值为Context的方法providersContext().
  • 最后就成功的构建了实例化对象。
注:在编写Module中,不能出现传入参数和返回参数一致的情况,会导致死循环。

很容易理解,需要的和获取的是同一个方法,循环调用。

举报

相关推荐

0 条评论