为了账号安全,请及时绑定邮箱和手机立即绑定

Dagger2在Android中的使用

标签:
Android

在我们写程序的过程中,不可避免的就会牵扯到一些依赖,如会创建各种工厂类来生产我们所要依赖的对象等等。太多依赖会让我们的程序看起来很乱,而且很不利于测试,所以我们就使用Dagger2来进行依赖注入。

依赖注入到底是个什么概念呢?我自己的理解就是将对象的生产和使用给分开了。比如说有一个Car对象,当你要出行的时候就自己new一个Car对象,然后使用这个Car对象出行。在这里你出行的时候Car就是你的依赖,没有这个Car就无法出行,所以就自己来创建这个Car。如果使用依赖注入了呢?创建和使用Car是分隔开的,创建的地方不考虑使用,使用的时候也不用考虑来创建,只要说我需要一辆Car,Dagger2就会自动帮你创建好并让你使用。这就在一定程度上解耦了程序,让你的模块更加地可以重用。

下面我们就在Android中试试Dagger2吧。但是首先还要弄清楚一些概念:

  1. @Inject: 可以用在构造方法上,这样就告诉Dagger2使用这个构造方法来创建对象,如果构造方法里面有参数依赖的话会自动给填充上;也可以用在成员变量上,Dagger2会自动将这个变量初始化。用@Inject修饰的内容可以理解为产品

  2. @Provides: 用来修饰方法来提供各种依赖,方法的返回类型就是所提供的依赖类型,用@Provides修饰的可以理解为生产机器

  3. @Module:所有的@Provides方法都必须放到一个Moudle中,一个Moudle就是使用@Moudle修饰的类,可以理解为一个工厂

  4. @Component:修饰一个接口,将依赖的生产和使用结合起来,可以理解为运输部门吧,将工厂生产的产品运送到使用它的人们手里。

光看文字可能还不是很明白,下面就来写代码实践吧。在这里我使用一个展示炉石传说卡片的app作为例子,我们使用Retrofit来访问网络接口,得到卡片的信息等。那我们会有哪些依赖呢?

  1. ApplicationContext对象,在Android app中使用十分广泛,比如我们需要获取资源文件等。

  2. 一个okHttpClient的对象,供Retrofit使用

  3. 一个使用Retrofit创建的网络访问的对象

  4. 可能会用到的Application对象

下面就一步步来吧,首先我们创建一个Moudle来提供对okHttpClient的依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Module
public class NetworkModule {
    @Provides
    @NonNull
    @Singleton
    public OkHttpClient provideOkHttpClient() {

        OkHttpClient okHttpClient = new OkHttpClient();

        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(BuildConfig.DEBUG ? BODY : NONE);

        OkHttpClient newClient = okHttpClient.newBuilder()
                .addInterceptor(httpLoggingInterceptor)
                .build();
        return newClient;
    }
}


通过@Singleton注释可以确保这个OkHttpClient对象是一个单例模式,对于这个client对象,我们加入了HttpLoggingInterceptor来控制log的显示,便于调试。

下面来创建一个网络访问的Moudle,在这之前我们还要定义好网络访问的接口:

1
2
3
4
5
6
7
8
public interface IApi {
    @Headers({
            "X-Mashape-Key:U4y8yvgRDUmshqUkNb1LJxmsRCBap1WWG0wjsnUj07GxYfsKUI",
            "Accept: application/json"
    })
    @GET("info")
    Observable<Info> getInfo();
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Module
public class ApiModule {
    private static final String BASE_URL = "https://omgvamp-hearthstone-v1.p.mashape.com";

    @Provides
    @Singleton
    public IApi getCardsApi(OkHttpClient client) {

        Retrofit CardsApiAdapter = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build();
        return CardsApiAdapter.create(IApi.class);
    }
}

我们将使用Rxjava来处理网络返回的内容,并内置一个GsonConverterFactory来将请求的Gson信息自动转化成对象的Bean。需要注意的是getCardsApi的参数就是一个OkHttpClient对象,由于我们在前面提供了对OkHttpClient的依赖,所以这里使用的是会自动传进一个OkHttpClient对象。

下面来创建提供Conext和Application的Moudle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Module
public class AppModule {
    private final MainApp mainApp;
    private final Context mContext;

    public AppModule(MainApp mainApp, Context mContext) {
        this.mainApp = mainApp;
        this.mContext = mContext;
    }

    @Provides
    @Singleton
    public MainApp getMainApp() {
        return mainApp;
    }

    @Provides
    @Singleton
    public Context provideApplicationContext() {
        return mContext;
    }
}


这些Moudle提供了所有我们需要的依赖,下面使用一个Component接口来将这些Moudle结合起来

1
2
3
4
5
6
7
8
9
@Singleton
@Component(modules = {AppModule.class, NetworkModule.class, ApiModule.class,})
public interface AppComponent {
    void inject(MainApp app);

    void inject(MainActivity mainActivity);

}


在这里接口里,我们定义了两个inject方法,我们将在MainApp和MainActivity里面使用Moudle里面提供的依赖。
在MainApp里面,我们创建一个AppComponent对象进行依赖的注入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class MainApp extends Application {
    private Context mContext;

    public AppComponent getmAppComponent() {
        return mAppComponent;
    }

    private AppComponent mAppComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = getApplicationContext();
        initializeInjector();
    }

    private void initializeInjector() {
        mAppComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this, mContext))
                .networkModule(new NetworkModule())
                .apiModule(new ApiModule())
                .build();
        mAppComponent.inject(this);
    }
}


需要注意的一点就是里面DaggerAppComponent是由Dagger2自动生成的类,所以我们再写这些代码前要首先编译一下工程,让Dagger2生成这些类,否则是会报错的。

下面就在Activity里面使用吧,首先也是进行注入:

1
2
3
4
5
6
7
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);
    ((MainApp) getApplication()).getmAppComponent().inject(this);
}


然后就可以直接进行网络的访问了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Inject
IApi mIApi;

@OnClick(R.id.text)
void () {
    CLogger.i("");
    Observable<Info> info = mIApi.getInfo();
    info.subscribeOn(Schedulers.io())
            .subscribe(new Subscriber<Info>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {
                    CLogger.e(e);
                }

                @Override
                public void onNext(Info info) {
                    CLogger.i(info.patch);
                }
            });
}


在这里,我们访问网络所需要的mIApi对象将由Dagger2自动给我们生成,我们拿过来用就可以了。赶快来实验一下吧,通过log,我们可以看到我们正确地请求到了所要的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
02-18 15:14:43.061 15902-15902/cn.com.mushuichuan.heartstonecards I/CLogger: MainActivity.java[Line: 26] 
02-18 15:14:43.061 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: --> GET https://omgvamp-hearthstone-v1.p.mashape.com/info http/1.1
02-18 15:14:43.061 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: X-Mashape-Key: U4y8yvgRDUmshqUkNb1LJxmsRCBap1WWG0wjsnUj07GxYfsKUI
02-18 15:14:43.061 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: Accept: application/json
02-18 15:14:43.061 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: --> END GET
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: <-- 200 OK https://omgvamp-hearthstone-v1.p.mashape.com/info (2317ms)
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: Cache-Control: private, must-revalidate
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: Content-Type: application/json
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: Date: Thu, 18 Feb 2016 07:14:49 GMT
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: expires: -1
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: pragma: no-cache
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: Server: Mashape/5.0.6
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: Set-Cookie: XSRF-TOKEN=eyJpdiI6ImRrT1dUN1dcLzVPcnlzVTRZNlVXUURRPT0iLCJ2YWx1ZSI6ImJYNkRONURJeEJTVW9ydndKeGM0Q1RQMmdYR3JzcTgxKzJtOGtcL0FKRHpNNEtaWStiVURMSVFTWldTY0lrdTR4bG1CYnJQN1JKNDRsXC82M25tS0pyNVE9PSIsIm1hYyI6IjdmNjVjYmJmMjZlYzQ0YjM4ZWZmYmVhYThhZDA5MzYxN2Y5OGFjODc3YmM1ODI4NjAwMjNiZTlhOWJlNDljNjQifQ%3D%3D; expires=Thu, 18-Feb-2016 09:14:49 GMT; Max-Age=7200; path=/
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: Set-Cookie: laravel_session=eyJpdiI6ImMwQnZ3QXVDUWNIMVNNT1Z2bUR1VlE9PSIsInZhbHVlIjoiODFndUFnYlBENUVoMXQ0TThsWmFzQldLN2Y0NUR0TTluaE1mMEZZdExwTVVtaFBySTB1K1wvRzFZQThCQVdrbXRHQkxtVExURVJycWRkc2ZrMmZpNXRRPT0iLCJtYWMiOiI3NDAxYzM1ZDA0MzkyYjMxNzlmNzk2YmNmNGM5OTc5NDU2YmY1MTY4OGU1NTQyMTE3ZDY5NmNlMWNjZmI0ODAwIn0%3D; expires=Thu, 18-Feb-2016 09:14:49 GMT; Max-Age=7200; path=/; httponly
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: X-Powered-By: PHP/5.6.13
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: Content-Length: 681
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: Connection: keep-alive
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: OkHttp-Sent-Millis: 1455779684200
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: OkHttp-Received-Millis: 1455779685387
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: {"patch":"4.1.0.10956","classes":["Druid","Hunter","Mage","Paladin","Priest","Rogue","Shaman","Warlock","Warrior","Dream"],"sets":["Basic","Classic","Credits","Naxxramas","Slush","Goblins vs Gnomes","Missions","Promo","Reward","System","Blackrock Mountain","Hero Skins","Tavern Brawl","The Grand Tournament","The League of Explorers"],"types":["Hero","Minion","Spell","Enchantment","Weapon","Hero Power"],"factions":["Horde","Alliance","Neutral"],"qualities":["Free","Common","Rare","Epic","Legendary"],"races":["Demon","Dragon","Mech","Murloc","Beast","Pirate","Totem"],"locales":["deDE","enGB","enUS","esES","esMX","frFR","itIT","koKR","plPL","ptBR","ruRU","zhCN","zhTW","jaJP"]}
02-18 15:14:45.381 15902-16339/cn.com.mushuichuan.heartstonecards D/OkHttp: <-- END HTTP (681-byte body)
02-18 15:14:45.391 15902-16339/cn.com.mushuichuan.heartstonecards I/CLogger: MainActivity.java[Line: 42] 4.1.0.10956


实验成功,可以继续进行接下来的开发了。

完整代码请见Github

原文链接:http://www.apkbus.com/blog-705730-60411.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消