博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Dagger2依赖注入
阅读量:6756 次
发布时间:2019-06-26

本文共 8630 字,大约阅读时间需要 28 分钟。

使用依赖

annotationProcessor 'com.google.dagger:dagger-compiler:2.2'    compile 'com.google.dagger:dagger:2.2'    provided 'javax.annotation:jsr250-api:1.0'

1. 先创建最基本的四个类

img_11e025805d51977ccf934c24ea9c2155.png
图1.png

代码:

/** * @author mazaiting * @date 2018/1/8 */public class Config {    public static final String TAG = "Config";}/** * 引擎 * @author mazaiting * @date 2018/1/8 */public class Engine {    public Engine(){        Log.e(Config.TAG, "Engine: new Engine()");    }}/** * 轮子 * @author mazaiting * @date 2018/1/8 */public class Wheel {    public Wheel(){        Log.e(Config.TAG, "Wheel: new Wheel()");    }}/** * 车座 * @author mazaiting * @date 2018/1/8 */public class Seat {    public Seat(){        Log.e(Config.TAG, "Seat: new Seat()");    }}

2. Dagger2是一个依赖注入的框架。

  • 之前我们写代码如下, Car类依赖于其他三个类,并且在构造方法中创建其他三个类的对象,这样,Car类在构造方法中对其他三个类的耦合度较高
/** * 车 * @author mazaiting * @date 2018/1/8 */public class Car {    private Engine mEngine;    private Seat mSeat;    private Wheel mWheel;    public Car() {        mEngine = new Engine();        mSeat = new Seat();        mWheel = new Wheel();        Log.e(Config.TAG, "Car: new Car()");    }}

执行Android单元测试:

img_85ecd8b7790b27c44463c25e9ae43061.png
图2.png
/** * @author mazaiting * @date 2018/1/9 */public class CarTest {    @Test    public void testCar(){        new Car();    }}
  • 使用Dagger2之后,先要创建一个CarModule类,再创建一个CarComponent接口或者抽象类,接下来Ctrl+F9进行编译,如果编译成功,则会生成DaggerCarComponent类(生成的Dagger开头,并且后面为Component组件的接口名/抽象类名),这个类提供注册Module类和注入当前类。

    img_034504c7d83721f9693676ef35b7d640.png
    图3.png
/** * @Module用来管理并提供依赖 * @Provides用来提供依赖 * @author mazaiting * @date 2018/1/8 */@Modulepublic class CarModule {    @Provides    public Engine provideEngine(){        return new Engine();    }    @Provides    public Seat provideSeat(){        return new Seat();    }    @Provides    public Wheel provideWheel(){        return new Wheel();    }    }/** * 组件 * @author mazaiting * @date 2018/1/8 */@Component(modules = CarModule.class)public interface CarComponent {    /**     * 实现注入     * @param car     */    void inject(Car car);}/** * 车 * @author mazaiting * @date 2018/1/8 */public class Car {    @Inject Engine mEngine;    @Inject Seat mSeat;    @Inject Wheel mWheel;    public Car() {        DaggerCarComponent                .builder()                .carModule(new CarModule())                .build()                .inject(this);        Log.e(Config.TAG, "Car: new Car()");    }}//  Component抽象类实现法/** * @author mazaiting * @date 2018/1/9 */@Component(modules = CarModule.class)public abstract class CarComponent {    /**     * @param car     */    public abstract void inject(Car car);}

执行上一步的Android单元测试,打印结果

img_6616a87f2d3c390d4f8e6e5cfa3729a4.png
图4.png

3. 以上用到的注解解释

  • @Module 标注用来管理并提供依赖。里面定义一些用@Provides注解的以provide开头的方法,这些方法就是所提供的依赖,Dagger2会在该类中寻找实例化某个类所需要的依赖。
  • @Provides 标注用来提供依赖
  • @Component 标注接口或者抽象类,用来将@Inject和@Module联系起来的桥梁,从@Module中获取依赖并将依赖注入给@Inject。参数module,用来指定用注解@Module标识的类。
  • @Inject 标注目标类中所依赖的其他类,标注所依赖的其他类的构造函数

4. 多个构造方法

1). 给Engine类添加一个构造方法

/** * 引擎 * @author mazaiting * @date 2018/1/8 */public class Engine {    public Engine(){        Log.e(Config.TAG, "Engine: new Engine()");    }    public Engine(String string){        Log.e(Config.TAG, "Engine: " + string);    }}

2). 此时运行之前的Android单元测试,发现它默认调用的是无参数的构造方法

img_bcd132876e4e85be0ed246b77bb10c78.png
图5.png

3). 但此时我们就想让它去调用含一个参数的构造方法,我们可以这么做

I>. 自定义一个注解,必须使用@Qualifier修饰器

/** * 标识引擎的颜色 * @author mazaiting * @date 2018/1/9 */@Qualifier@Documented@Retention(RetentionPolicy.RUNTIME)public @interface EngineString {    String string() default "white";}

II>. 在CarModule中添加一个提供Engine的方法,并使用刚刚自定义的注解

@Modulepublic class CarModule {    @Provides    public Engine provideEngine(){        return new Engine();    }// ... 省略其他的方法    @EngineString(string = "black")    @Provides    public Engine provideStringEngine(){        return new Engine("black");    }}

III>. 在Car类中,声明Engine的使用,同样也使用刚刚自定义的注解标识

/** * 车 * @author mazaiting * @date 2018/1/8 */public class Car {    @EngineString(string = "black")    @Inject Engine mEngine;    @Inject Seat mSeat;    @Inject Wheel mWheel;    public Car() {        DaggerCarComponent                .builder()                .carModule(new CarModule())                .build()                .inject(this);        Log.e(Config.TAG, "Car: new Car()");    }}

IV>. 使用之前的Android单元测试

img_95ed6976f6a97fa4f315b78cbf0f6d0e.png
图6.png

5. @Named注解

@Named 是基于@Qualifier的注解,不过只能传递字符串

@Qualifier 包括但不限于字符串,如枚举等。

6. Lazy<T>懒加载数据

public class Car {    @EngineString(string = "black")    @Inject Engine mEngineBlack;    @Named(value = "10")    @Inject Engine mEngine;    @Inject Seat mSeat;    @Inject    Lazy
mWheelLazy; public Car() { DaggerCarComponent .builder() .carModule(new CarModule()) .build() .inject(this); Log.e(Config.TAG, "Car: new Car()"); } // 使用懒加载的变量 public void useWheel(){ mWheelLazy.get(); }}

新建Android 单元测试

@Test    public void testCar1(){        final Car car = new Car();        new Thread(new Runnable() {            @Override            public void run() {                Log.e("tag", "useWheel" + Thread.currentThread());                car.useWheel();            }        }).start();    }

单元测试打印结果:

img_f1a43e063f8a28a3b90406db2a408c4f.png
图7.png

7. @Singleton 当前提供的对象将是单例模式 ,一般配合@Provides一起出现。

8. 使用示例

AppModule.java

/** * @author mazaiting * @date 2018/1/9 */@Modulepublic class AppModule {    Application mApplication;    public AppModule(Application application){        this.mApplication = application;    }    @Provides    @Singleton    Application provideApplication(){        return this.mApplication;    }}

NetModule.java

/** * @author mazaiting * @date 2018/1/9 */@Modulepublic class NetModule {    String mBaseUrl;    // Constructor needs one parameter to instantiate.    public NetModule(String baseUrl) {        this.mBaseUrl = baseUrl;    }    // Dagger will only look for methods annotated with @Provides    @Provides    @Singleton    // Application reference must come from AppModule.class    SharedPreferences providesSharedPreferences(Application application) {        return PreferenceManager.getDefaultSharedPreferences(application);    }    @Provides    @Singleton    Cache provideOkHttpCache(Application application) {        int cacheSize = 10 * 1024 * 1024; // 10 MiB        Cache cache = new Cache(application.getCacheDir(), cacheSize);        return cache;    }    @Provides    @Singleton    Gson provideGson() {        GsonBuilder gsonBuilder = new GsonBuilder();        gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);        return gsonBuilder.create();    }    @Provides @Named("cached")    @Singleton    OkHttpClient provideOkHttpClientCache(Cache cache) {        OkHttpClient.Builder builder = new OkHttpClient.Builder();        builder.cache(cache);        return builder.build();    }    @Provides @Named("non_cached")    @Singleton    OkHttpClient provideOkHttpClient() {        OkHttpClient.Builder builder = new OkHttpClient.Builder();        return builder.build();    }    @Provides    @Singleton    Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {        Retrofit retrofit = new Retrofit.Builder()                .addConverterFactory(GsonConverterFactory.create(gson))                .baseUrl(mBaseUrl)                .client(okHttpClient)                .build();        return retrofit;    }}

NetComponent.java

@Singleton@Component(modules = {AppModule.class, NetModule.class})public interface NetComponent {    /**     * @param activity     */    void inject(MainActivity activity);}

完成前三个类之后编译,生成DaggerNetComponent.java.

MyApp.java

public class MyApp extends Application {    private NetComponent mNetComponent;    @Override    public void onCreate() {        super.onCreate();        mNetComponent =                DaggerNetComponent                .builder()                .appModule(new AppModule(this))                .netModule(new NetModule("http://www.baidu.com/"))                .build();    }    public NetComponent getNetComponent(){        return mNetComponent;    }}

MainActivity.java

public class MainActivity extends AppCompatActivity {    @Inject @Named("cached")    OkHttpClient mClient;    @Inject @Named("non_cached")    OkHttpClient mOkHttpClient;    @Inject    SharedPreferences mSharedPreferences;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);//        new Car();        ((MyApp)getApplication()).getNetComponent().inject(this);    }    // 写数据    public void write(View view){        mSharedPreferences.edit().putString("key", "value").apply();    }    // 读数据    public void read(View view){        Toast.makeText(this, mSharedPreferences.getString("key", "string"), Toast.LENGTH_SHORT).show();    }}

activity_main.xml

转载地址:http://rfzeo.baihongyu.com/

你可能感兴趣的文章
C#调用c++创建的dll
查看>>
12.02个人博客
查看>>
Notification通知代码简洁使用
查看>>
UIView 动画
查看>>
ssh加密公私钥
查看>>
快速部署Python应用:Nginx+uWSGI配置详解
查看>>
mybatis-generator生成数据对象
查看>>
java Queue中 add/offer,element/peek,remove/poll区别
查看>>
一个继承了抽象类的普通类的执行顺序
查看>>
Map集合中key不存在时使用toString()方法、valueOf()方法和强制转换((String))之间的区别...
查看>>
ArcIMS 开发学习笔记(一)
查看>>
leetcode_1095. Find in Mountain Array_[Binary Search]
查看>>
关于搭建haddoop分布式系统的全部过程复习
查看>>
简单使用SOCKET,TCP,UDP模式之间的通信
查看>>
js历史返回
查看>>
JavaWeb之JavaMail
查看>>
430. Flatten a Multilevel Doubly Linked List - Medium
查看>>
ASP.NET MVC学前篇之Lambda表达式、依赖倒置
查看>>
空白不曾停止。。。
查看>>
python递归——汉诺塔
查看>>