前言
以为工作需求,所以最近补了补之前没了解过的Dagger2的内容,基础篇已经发布。接下来就是Dagger2在Android中的应用了。当然,和我一样刚接触Dagger2的朋友,可以先看一下之前的基础文章:
翻译给刚入Dagger这个坑的Android开发者:DI入门篇
正文
这篇文章的Demo实在是太好了。所以我就厚颜无耻的把他的代码拿过来用...这是一个外国哥们的文章,我猜他应该不会怪我的,哈哈...
原文地址:[Dagger 2 for Android Beginners?—?Advanced part I](https://medium.com/@harivigneshjayapalan/dagger-2-for-android-beginners-advanced-part-i-1e14fccf2cc8)
进入正文之前,我们先看一下背景。代码需求很简单,从一个API上获取数据,然后加载到RecycleView上,并且会涉及到图片加载。
在这么一个需求之下,我们如果使用Dagger2为我们的工程提供相应的依赖呢?
简单罗列一下代码设计
- MainActivity.java:请求API并显示项目 RecyclerView
- Result.java:用于API响应的POJO,使用JSON Schema创建到POJO
- RandomUsersAdapter.java:适配器 RecyclerView
涉及以下依赖项和库。
- Retrofit
- GsonBuilder&Gson
- HttpLoggingInterceptor
- OkHttpClient
- Picasso
以上内容不重要,都是咱们日常开发常用的东西。怎么使用啥的,大家肯定都很属性,所以下文demo很多初始化啥的就跳过了,咱们的关注是Dagger2在Android中的应用。
注意,这里不是叭叭叭的贴代码,讲API,而是从一个业务出发,以Dagger2的角度讲解Daager2的依赖关系,相信你们会我和一样,看完一定会“拨云雾见青天”,哈哈~
一般解决方案
面对这种需求,我们的常规写法:
public class MainActivity extends AppCompatActivity {
// 省略变量声明
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 省略View的初始化
// 省略Gson初始化
// 省略HttpLoggingInterceptor及OkHttpClient初始化
// 不省略太多了,免得失去代入感,哈哈。
retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl("https://randomuser.me/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
populateUsers();
}
// 网络请求
private void populateUsers() {
Call<RandomUsers> randomUsersCall = getRandomUserService().getRandomUsers(10);
randomUsersCall.enqueue(new Callback<RandomUsers>() {
@Override
public void onResponse(Call<RandomUsers> call, @NonNull Response<RandomUsers> response) {
if(response.isSuccessful()) {
mAdapter = new RandomUserAdapter();
mAdapter.setItems(response.body().getResults());
recyclerView.setAdapter(mAdapter);
}
}
// 省略请求失败
});
}
public RandomUsersApi getRandomUserService(){
return retrofit.create(RandomUsersApi.class);
}
}
public class RandomUserAdapter extends RecyclerView.Adapter<RandomUserAdapter.RandomUserViewHolder> {
private List<Result> resultList = new ArrayList<>();
public RandomUserAdapter() {}
@Override
public RandomUserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_random_user,
parent, false);
return new RandomUserViewHolder(view);
}
@Override
public void onBindViewHolder(RandomUserViewHolder holder, int position) {
Result result = resultList.get(position);
// setText操作
holder.textView.setText(String.format("%s %s", result.getName().getFirst(),
result.getName().getLast()));
// 图片库加载图片
Picasso.with(holder.imageView.getContext())
.load(result.getPicture().getLarge())
.into(holder.imageView);
}
// 省略部分代码
}
写完上述代码之后,让我们挺一分钟,想一想我们刚才写的东西,是不是有明显的依赖关系?比如,我们的Activity依赖Retrofit,我们的Retrofit又依赖OkHttp等等这种关系。
而且,所有的初始化操作都其中在Activity做了处理,如果此时我们需要更多的Activity,难道还有一遍遍写重复的代码?
当然可能有朋友会说可以使用基类,或者单例等等的封装方式。不过今天我们通通不考虑这些,今天只聊Dagger2
上述的业务其实还很多内容没有考虑到,比如说缓存...因此我们的业务如果更精细一些会发现,还有依赖更多的模块:
- File/DB: 持久化缓存
- 内存Cache: 内存缓存
- OkHttp3Downloader: 下载模块
所以如果完整的展开代码,应该是这样的:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
// Gson依赖
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
// File持久化依赖
File cacheFile = new File(this.getCacheDir(), "HttpCache");
cacheFile.mkdirs();
// Cache内存依赖
Cache cache = new Cache(cacheFile, 10 * 1000 * 1000); //10 MB
// Log依赖
HttpLoggingInterceptor httpLoggingInterceptor = new
HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(@NonNull String message) {
Timber.i(message);
}
});
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
// OkHttp依赖
OkHttpClient okHttpClient = new OkHttpClient()
.newBuilder()
.cache(cache)
.addInterceptor(httpLoggingInterceptor)
.build();
OkHttp3Downloader okHttpDownloader = new OkHttp3Downloader(okHttpClient);
// Picasso依赖
picasso = new Picasso.Builder(this).downloader(okHttpDownloader).build();
// Retrofit依赖
retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl("https://randomuser.me/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
populateUsers();
}
作为“久经沙场”的老司机,这些都是家常便饭,便饭之余我们聊一些茶语饭后的话题:从这些初始化代码中抽象出一个依赖图。就如果Retrofit初始化时传了一个Gson,那就说明Retrofit依赖Gson...
因此,我们差不多能够梳理一个依赖关系图:
绿色框表示它们是依赖关系中的顶级的(任何模块都不想要依赖它),它们只会被依赖。
结合我们写过的初始化代码,这个图很好理解吧?我猜肯定有朋友这张图都已经在写下代码之时出现在脑海中了...
走到这一步,其实问题就已经显现出来了。这么庞大的初始化的过程,任谁都不会想再写第二遍。因此重构迫在眉睫。既然我们都已经捋清楚了我们所需要模块的依赖关系,那么接下来就是让Dagger2大展身手的时候了...
尾声
因为篇幅原来,怕各位一次看太多的内容,效率不高,所以这里将其一分而二,Dagger2重构部分,欢迎关注我,后续在我的文章里边中阅读~

本文暂时没有评论,来添加一个吧(●'◡'●)