編輯:關於Android編程
原文鏈接:http://code.tutsplus.com/tutorials/dependency-injection-with-dagger-2-on-android–cms-23345
依賴注入是一種軟件設計模式,致力於應用松耦合,可擴展性和可維護性。本教程中,將學到如何使用Dagger2進行依賴注入。
當一個對象需要或依靠其他對象處理工作時,這就是一個依賴關系。依賴關系可以通過讓依賴對象創建被依賴者或者使用工廠方法創建一個被依賴者來解決。在依賴注入的情況下,然而,向類提供的依賴需要避免類來創建它們。這樣你創建的軟件就是松耦合和高可維護的。
本教程使用Dagger的最新版,Dagger 2。在寫作期間,Dagger 2還未正式發布,處於pre-alpha階段。然而,它是可用和穩定的。你可以訪問Dagger on GitHub得到項目的新聞和正式版的發布日期。
你需要在開發機上安裝最新版的Android Studio,可以從Android開發者網站下載。
Dagger 2提供了一些特殊的注解:
@Module
用於類,該類的方法提供依賴。
@Provides
用於@Module
注解的類中的方法
@inject
請求依賴(用在構造函數,域或方法)
@Component
是模塊和注入之間的接口
這些就是即將使用Dagger 2進行依賴注入所需要了解的重要注解。我將在一個簡單Android應用中向你展示如何使用它們。
為了正確使用Dagger 2,你需要遵守以下步驟:
識別依賴對象和它的依賴。 創建帶@Module
注解的類,對每個返回依賴的方法使用@Provides
注解。
在依賴對象上使用@Inject
注解來請求依賴。
使用@Componet
注解創建一個接口並增加第二步中創建的帶@Module
注解的類。
創建一個@Component
接口的對象來實例化自帶依賴的依賴對象。
依賴分析從運行時轉換到編譯時。這意味著在開發階段就可以知道可能的問題,而不像其他的庫,例如Guice。在開始使用Dagger 2庫之前,你需要安裝Android Stuido來訪問生成的類。
使用Android Studio創建一個新的應用並命名。我的工程命名為TutsplusDagger。
設置項目的最小SDK版本為API 10來適配更多機型。
創建的activity選擇空布局。對於本教程,不需要特殊布局。
命名activity為Main
Activity並點擊Finish按鈕。
工程創建後,你需要對gradle文件進行一些修改。讓我們在下一步中做這些改動。
我們需要修改工程的build.gradle文件如下:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
allprojects {
repositories {
mavenCentral()
maven{
url 'https://oss.sonatype.org/content/repositories/snapshots/'
}
}
}
讓我們看一下做了哪些修改:
- dependencies:這部分,我增加了一個插件,該插件將用於訪問Dagger生成的文件。如果不加入,訪問這些新類時將看到錯誤。
- allprojects:這個修改是因為我們使用的庫當前處於pre-alpha階段,而且這是使用Maven來訪問該庫的唯一可用地址。也可以從Sonatype下載Dagger和Dagger編譯器庫,但本教程是基於Maven倉庫創建的。
####Step 2
打開工程app文件夾中的build.gradle文件,修改如下:
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.androidheroes.tutsplusdagger"
minSdkVersion 10
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.google.dagger:dagger:2.0-SNAPSHOT'
apt 'com.google.dagger:dagger-compiler:2.0-SNAPSHOT'
provided 'org.glassfish:javax.annotation:10.0-b28'
}
在文件開頭,我應用了新的插件。務必將新插件(com.neenbedankt.android-apt)放到Android插件之後。如果不這樣做,在同步工程的gradle文件時將顯示錯誤。
在dependencies中添加了如下依賴:
- dagger庫
- dagger-compiler用於代碼生成
- javax.annotation用於Dagger之外需求的額外注解
在更新Dagger的配置後,你需要點擊上面的按鈕來同步工程的gradle文件。
到這裡,你的應用已經有了一個可以准備使用的空項目。如果有錯誤,請確保你正確的遵守以上步驟。現在我們來實現我們的栗子項目。
對於本教程,我打算實現兩個類,Vehicle
和Motor
。Motor
是獨立類,Vehicle
是依賴類。我打算開始在包名為model
中創建這個模型。
Motor
類結構如下:
package com.androidheroes.tutsplusdagger.model;
/**
* Created by kerry on 14/02/15.
*/
public class Motor {
private int rpm;
public Motor(){
this.rpm = 0;
}
public int getRpm(){
return rpm;
}
public void accelerate(int value){
rpm = rpm + value;
}
public void brake(){
rpm = 0;
}
}
該類只有一個名為rmp
的屬性,我准備通過accelerate
和brake
方法來修改它。並且使用getRpm
方法來訪問當前值。
Vehicle
類結構如下:
package com.androidheroes.tutsplusdagger.model;
/**
* Created by kerry on 14/02/15.
*/
public class Vehicle {
private Motor motor;
public Vehicle(Motor motor){
this.motor = motor;
}
public void increaseSpeed(int value){
motor.accelerate(value);
}
public void stop(){
motor.brake();
}
public int getSpeed(){
return motor.getRpm();
}
}
在類中,你看到我沒有創建Motor
類的新對象,即使使用了它的方法。在真實世界的應用中,這個類應當有更多的方法和屬性,但現在盡量保持簡單。
####Step 2:創建@Module
類
現在要創建帶@Module
注解的類。該類將提供自帶依賴的對象。因為這點,需要創建新的包名(只是為了保持順序),命名為module
並在其中增加新類,代碼如下:
package com.androidheroes.tutsplusdagger.module;
import com.androidheroes.tutsplusdagger.model.Motor;
import com.androidheroes.tutsplusdagger.model.Vehicle;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
/**
* Created by kerry on 14/02/15.
*/
@Module
public class VehicleModule {
@Provides @Singleton
Motor provideMotor(){
return new Motor();
}
@Provides @Singleton
Vehicle provideVehicle(){
return new Vehicle(new Motor());
}
}
在Step 1中我指出,Vehicle
需要Motor
來正常工作。這就是為什麼你需要創建兩個提供者,一個給Motor
(獨立模型),另一個給Vehicle
(指明它的依賴)。
別忘了每個提供者(或方法)必須添加@Provides
注解並且類必須有@Module
注解。@Singleton
注解指明對象只能有一個實例。
####Step 3: 依賴對象中請求依賴
現在不同的模型都有了提供者,你需要請求它們。就像Vehicle
需要Motor
那樣,你需要在Vehicle
的構造函數前增加@Inject
注解,代碼如下:
@Inject
public Vehicle(Motor motor){
this.motor = motor;
}
你可以使用@Inject
注解在構造函數,域,方法中來請求依賴。這個例子裡,我在構造函數中使用注入。
####Step 4:使用@Inject
鏈接@Module
使用帶@Component
注解的接口連接依賴的提供者,@Module
,和請求他們的類,這些類標記了@Inject
package com.androidheroes.tutsplusdagger.component;
import com.androidheroes.tutsplusdagger.model.Vehicle;
import com.androidheroes.tutsplusdagger.module.VehicleModule;
import javax.inject.Singleton;
import dagger.Component;
/**
* Created by kerry on 14/02/15.
*/
@Singleton
@Component(modules = {VehicleModule.class})
public interface VehicleComponent {
Vehicle provideVehicle();
}
@Component
注解中,你需要指明打算使用哪個類 —— 本例是VehicleModule
,前面已經創建了。如果你打算使用更多的模塊,只需要使用逗號作為分隔符來增加它們。
接口中,給每個需要的對象增加方法,它們會自動添加依賴。本例中,因為只需要一個Vehicle
對象,所以只有一個方法。
####Step 5: 使用@Component
接口獲取對象
現在萬事俱備了,你需要擁有一個接口的實例並調用它的方法來獲取需要的對象。我將在MainActivity
中的OnCreate
方法中實現,代碼如下:
package com.androidheroes.tutsplusdagger;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.widget.Toast;
import com.androidheroes.tutsplusdagger.component.Dagger_VehicleComponent;
import com.androidheroes.tutsplusdagger.component.VehicleComponent;
import com.androidheroes.tutsplusdagger.model.Vehicle;
import com.androidheroes.tutsplusdagger.module.VehicleModule;
public class MainActivity extends ActionBarActivity {
Vehicle vehicle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
VehicleComponent component = Dagger_VehicleComponent.builder().vehicleModule(new VehicleModule()).build();
vehicle = component.provideVehicle();
Toast.makeText(this, String.valueOf(vehicle.getSpeed()), Toast.LENGTH_SHORT).show();
}
當你打算創建一個帶@Component
注解的接口對象時,你需要使用Dagger_
前綴來實現,本例是Dagger_VehicleComponent
,然後使用builder
方法來調用各個模塊。
秘訣就在代碼的第23行。你只要求Vehicle
類的一個對象,Dagger2庫會負責准備該對象的所有依賴。同樣,你看不到其他任何對象的新實例——Dagger2庫幫你處理了所有。
現在可以在設備或者模擬器上運行應用。如果按照教程一步一步實現,你將看到一個顯示rpm
變量初始值的Toast
消息。
在相關的工程裡,你能看到一個對MainActivity
類定制的用戶接口,該接口中,通過點擊屏幕上的按鈕,你可以修改rpm
變量的值。
依賴注入是一個模式,在你的應用中遲早會用到該模式。使用Dagger 2,你擁有了實現依賴注入的利器。我希望該教程對你有用,如果你喜歡它請分享它。
關於使用MarkDown編輯器的原因 其實前段時間就支持使用MarkDown編輯器來寫博客了,只是由於當時接觸過MarkDown,所以之前的博客都是使用默認的HTML編輯
1.Logger 是什麼在我們日常的開發中,肯定是少不了要和 Log 打交道,回想一下我們是怎麼使用 Log 的:先定義一個靜態常量 TAG,TAG 的值通常是當前類的類
實現效果如下:實現思路:1、如何實現圓中水面上漲效果:利用Paint的setXfermode屬性為PorterDuff.Mode.SRC_IN畫出進度所在的矩形與圓的交集
安卓消息處理類:Looper、Handler、MessageQueue、Message、ThreadLocal、ThreadLocal.Values、HandlerThr