本文的合集已經(jīng)編著成書,高級(jí)Android開發(fā)強(qiáng)化實(shí)戰(zhàn)笙以,歡迎各位讀友的建議和指導(dǎo)匙瘪。在京東即可購(gòu)買:https://item.jd.com/12385680.html
Dagger已經(jīng)加入Google I/O, 是Square開發(fā)的依賴注入庫(kù), 發(fā)布2.0版本. Dagger表示有向非循環(huán)圖(Directed Acyclic Graph, DAGger). 好處和優(yōu)點(diǎn)有很多, 參考, 所有優(yōu)秀的開源庫(kù), 本質(zhì)上都是讓程序更加清晰, 編寫更加容易. 讓我們來看看怎么使用?
主要內(nèi)容:
(1) 項(xiàng)目的配置環(huán)境.
(2) Inject\Module\Component的使用方法.
(3) 結(jié)合Retrofit和RxAndroid.
本文源碼的GitHub下載地址
1. 配置
從一個(gè)最簡(jiǎn)單的HelloWorld開始, 設(shè)置build.gradle
, 并添加依賴庫(kù).
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
// Lambda表達(dá)式
plugins {
id "me.tatarka.retrolambda" version "3.2.4"
}
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt' // 注釋處理
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "clwang.chunyu.me.wcl_dagger_demo"
minSdkVersion 17
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// 注釋沖突
packagingOptions {
exclude 'META-INF/services/javax.annotation.processing.Processor'
}
// 使用Java1.8
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1' // RecyclerView
compile 'com.jakewharton:butterknife:7.0.1' // 標(biāo)注
compile 'com.google.dagger:dagger:2.0.2' // dagger2
compile 'com.google.dagger:dagger-compiler:2.0.2' // dagger2
compile 'io.reactivex:rxandroid:1.1.0' // RxAndroid
compile 'io.reactivex:rxjava:1.1.0' // 推薦同時(shí)加載RxJava
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' // Retrofit網(wǎng)絡(luò)處理
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' // Retrofit的rx解析庫(kù)
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' // Retrofit的gson庫(kù)
provided 'javax.annotation:jsr250-api:1.0' // Java標(biāo)注
}
Gradle的配置與功能.
android-apt
, 提供dagger2使用編譯生成類的功能.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
apply plugin: 'com.neenbedankt.android-apt' // 注釋處理
retrolambda
, 提供Lambda表達(dá)式支持的功能.
// Lambda表達(dá)式
plugins {
id "me.tatarka.retrolambda" version "3.2.4"
}
android{
...
// 使用Java1.8
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
recyclerview
, 提供RecyclerView控件的功能.
compile 'com.android.support:recyclerview-v7:23.1.1' // RecyclerView
butterknife
, 提供xml至java的id映射的功能.
compile 'com.jakewharton:butterknife:7.0.1' // 標(biāo)注
dagger2
, 提供dagger2支持的功能.
compile 'com.google.dagger:dagger:2.0.2' // dagger2
compile 'com.google.dagger:dagger-compiler:2.0.2' // dagger2
rx
, 提供rxandroid和rxjava支持的功能.
compile 'io.reactivex:rxandroid:1.1.0' // RxAndroid
compile 'io.reactivex:rxjava:1.1.0' // 推薦同時(shí)加載RxJava
retrofit
, 提供網(wǎng)絡(luò)請(qǐng)求的支持的功能.
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' // Retrofit網(wǎng)絡(luò)處理
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' // Retrofit的rx解析庫(kù)
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' // Retrofit的gson庫(kù)
annotation
, 提供java注釋解析的功能.
provided 'javax.annotation:jsr250-api:1.0' // Java標(biāo)注
2. 主活動(dòng)
使用主頁跳轉(zhuǎn)頁面展示dagger2.
dagger2
主要包含inject
, module
, component
三個(gè)部分, 即:
Inject
, 依賴注入dependency injection
, 把定義的類注入聲明.
Module
, 模塊, 提供若干類, 在依賴注入中使用.
Component
, 組件, 注冊(cè)若干模塊至項(xiàng)目中.
提供圖接口, 在項(xiàng)目中, 使用注入的類.
/**
* Dagger2的圖接口
* <p/>
* Created by wangchenlong on 16/1/2.
*/
public interface DemoGraph {
void inject(MainActivity mainActivity); // 注入MainActivity
void inject(ReposListActivity reposListActivity); // 注入列表Activity
}
組件, 注冊(cè)Module, 添加主Module.
/**
* 組件
* Created by wangchenlong on 16/1/2.
*/
@Singleton
@Component(modules = {MainModule.class, ApiModule.class})
public interface DemoComponent extends DemoGraph {
final class Initializer {
private Initializer() {
} // No instances.
// 初始化組件
public static DemoComponent init(DemoApplication app) {
return DaggerDemoComponent.builder()
.mainModule(new MainModule(app))
.build();
}
}
}
如果沒有Module可以暫時(shí)不添加, 但是要提供類, 項(xiàng)目注冊(cè)需要使用中間類.
DaggerDemoComponent
是自動(dòng)生成的類, Dagger+類名.
項(xiàng)目的應(yīng)用, 把Application
添加至組件, 并提供注冊(cè)類的圖接口.
/**
* 應(yīng)用信息
* <p/>
* Created by wangchenlong on 16/1/2.
*/
public class DemoApplication extends Application {
private static DemoGraph sDemoGraph;
private static DemoApplication sInstance;
@Override public void onCreate() {
super.onCreate();
sInstance = this;
buildComponentAndInject();
}
public static DemoGraph component() {
return sDemoGraph;
}
public static void buildComponentAndInject() {
sDemoGraph = DemoComponent.Initializer.init(sInstance);
}
}
主活動(dòng), 注冊(cè)入圖, 并添加跳轉(zhuǎn)下一頁功能.
/**
* 主活動(dòng), 注冊(cè)類.
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
DemoApplication.component().inject(this); // 應(yīng)用注入
}
// 跳轉(zhuǎn)列表視圖
public void gotoReposList(View view) {
startActivity(new Intent(this, ReposListActivity.class));
}
}
主模塊, 提供Application和Resources.
/**
* 主要模塊, 提供Application和resources.
* <p/>
* Created by wangchenlong on 16/1/2.
*/
@Module
public class MainModule {
private final DemoApplication mApp;
public MainModule(DemoApplication application) {
mApp = application;
}
@Provides
@Singleton
protected Application provideApplication() {
return mApp;
}
@Provides
@Singleton
protected Resources provideResources() {
return mApp.getResources();
}
}
方法名添加
@Provides
和@Singleton
, 使用時(shí), 添加@Inject
即可. 表示在Module
中創(chuàng)建, 在其他類中, 可以任意注入使用.
方法的參數(shù), 因?yàn)闆]有調(diào)用方法的過程, 所以需要模塊(Module)提供.
3. 其他活動(dòng)
主要是列表展示GitHub用戶的庫(kù)信息, 使用Retrofit和RxAndroid的方法.
使用RecyclerView
展示庫(kù)信息, 注入類到圖中, 并注入Github服務(wù)
, Rx
分發(fā)信息.
/**
* 代碼庫(kù)列表
* <p>
* Created by wangchenlong on 16/1/2.
*/
public class ReposListActivity extends Activity {
@Bind(R.id.repos_rv_list) RecyclerView mRvList;
@Inject
GitHubService mGitHubService;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_repos_list);
ButterKnife.bind(this);
DemoApplication.component().inject(this);
LinearLayoutManager manager = new LinearLayoutManager(this);
manager.setOrientation(LinearLayoutManager.VERTICAL);
mRvList.setLayoutManager(manager);
ListAdapter adapter = new ListAdapter();
mRvList.setAdapter(adapter);
loadData(adapter);
}
// 加載數(shù)據(jù)
private void loadData(ListAdapter adapter) {
mGitHubService.getRepoData("SpikeKing")
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(adapter::setRepos);
}
}
適配器.
/**
* RecyclerView的Adapter
* <p>
* Created by wangchenlong on 16/1/2.
*/
public class ListAdapter extends RecyclerView.Adapter<ListAdapter.RepoViewHolder> {
private ArrayList<Repo> mRepos; // 庫(kù)信息
public ListAdapter() {
mRepos = new ArrayList<>();
}
public void setRepos(ArrayList<Repo> repos) {
mRepos = repos;
notifyItemInserted(mRepos.size() - 1);
}
@Override
public RepoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_repo, parent, false);
return new RepoViewHolder(view);
}
@Override public void onBindViewHolder(RepoViewHolder holder, int position) {
holder.bindTo(mRepos.get(position));
}
@Override public int getItemCount() {
return mRepos.size();
}
public static class RepoViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.item_iv_repo_name) TextView mIvRepoName;
@Bind(R.id.item_iv_repo_detail) TextView mIvRepoDetail;
public RepoViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bindTo(Repo repo) {
mIvRepoName.setText(repo.name);
mIvRepoDetail.setText(String.valueOf(repo.description + "(" + repo.language + ")"));
}
}
public static class Repo {
public String name; // 庫(kù)的名字
public String description; // 描述
public String language; // 語言
}
}
GitHub請(qǐng)求接口, 返回Rx的觀察者.
/**
* GitHub服務(wù)
* <p>
* Created by wangchenlong on 16/1/2.
*/
public interface GitHubService {
String ENDPOINT = "https://api.github.com";
// 獲取庫(kù), 獲取的是數(shù)組
@GET("/users/{user}/repos")
Observable<ArrayList<ListAdapter.Repo>> getRepoData(@Path("user") String user);
}
Api模塊, 使用請(qǐng)求接口創(chuàng)建GitHub服務(wù).
/**
* 接口模塊
* <p>
* Created by wangchenlong on 16/1/2.
*/
@Module
public class ApiModule {
@Provides
@Singleton
protected GitHubService provideGitHubService() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(GitHubService.ENDPOINT)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 添加Rx適配器
.addConverterFactory(GsonConverterFactory.create()) // 添加Gson轉(zhuǎn)換器
.build();
return retrofit.create(GitHubService.class);
}
}
不要忘記, 注冊(cè)模塊(Module)到組件(Component). 組件組成到應(yīng)用, 模塊注冊(cè)到組件.
dagger2的重要優(yōu)勢(shì)就是省略了很多重復(fù)的創(chuàng)建, 直接依賴注入非常簡(jiǎn)單.
效果
OK, that's all! Enjoy It!