2017-02-24 73 views
0

我已經在我的應用程序中設置了dagger2依賴項,並且通過很多示例瞭解它。我沒有找到的是一旦注入它們就可以使用所有依賴的正確方法。Dagger2使用整個依賴關係圖

模塊中的每個單例都依賴於之前單例的輸出。整個依賴關係圖是如何使用的,而不用調用每個單例來獲取所需的輸入?

考慮以下幾點:

AppComponent

@Singleton 
@Component(modules = { 
     DownloaderModule.class 
}) 
public interface AppComponent { 
    void inject(MyGameActivity activity); 
} 

DownloaderModule

@Module 
public class DownloaderModule { 

    public static final String NETWORK_CACHE = "game_cache"; 

    private static final int GLOBAL_TIMEOUT = 30; // seconds 

    public DownloaderModule(@NonNull String endpoint) { 
     this(HttpUrl.parse(endpoint)); 
    } 

    @Provides @NonNull @Singleton 
    public HttpUrl getEndpoint() { 
     return this.endpoint; 
    } 

    @Provides @NonNull @Singleton @Named(NETWORK_CACHE) 
    public File getCacheDirectory(@NonNull Context context) { 
     return context.getDir(NETWORK_CACHE, Context.MODE_PRIVATE); 
    } 

    @Provides @NonNull @Singleton 
    public Cache getNetworkCache(@NonNull @Named(NETWORK_CACHE) File cacheDir) { 
     int cacheSize = 20 * 1024 * 1024; // 20 MiB 
     return new Cache(cacheDir, cacheSize); 
    } 

    @Provides @NonNull @Singleton 
    public OkHttpClient getHttpClient(@NonNull Cache cache) { 
     return new OkHttpClient.Builder() 
       .cache(cache) 
       .connectTimeout(GLOBAL_TIMEOUT, TimeUnit.SECONDS) 
       .readTimeout(GLOBAL_TIMEOUT, TimeUnit.SECONDS) 
       .writeTimeout(GLOBAL_TIMEOUT, TimeUnit.SECONDS) 
       .build(); 
    } 

MyGameApp

public class MyGameApp extends Application { 

    private AppComponent component; 

    private static Context context; 

    public static MyGameApp get(@NonNull Context context) { 
     return (MyGameApp) context.getApplicationContext(); 
    } 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     component = buildComponent(); 
     MyGameApp.context = getApplicationContext(); 

     } 

    public AppComponent component() { 
     return component; 
    } 

    protected AppComponent buildComponent() { 
     return DaggerAppComponent.builder() 
       .downloaderModule(new DownloaderModule("https://bogus.com/")) 
       .build(); 
    } 

} 
+1

你是什麼意思,「取決於它之前的單身人士的產出」?看起來你的模塊結構良好,可以通過在相應的'@ Provide'方法中將每個部分作爲輸入參數來注入它需要的每個部分。你應該能夠注入'OkHttpClient'或者你從MyGameActivity中創建的任何其他依賴。 –

+0

我只是無法在腦海中找到它。我讀了更多,概念正在沉入其中。令人沮喪的是有大量文章顯示如何設置它,但實際使用示例很難找到。現在我正在用一個體面的例子。謝謝。 –

回答

1

我會嘗試一些光棚到這一點,但也有你可以閱讀的幾種方法。我更喜歡自下而上的方法 - 基本上開始你的對象需要和工作的方式。在這種情況下,我會從MyGameActivity開始。不幸的是,你並沒有爲此粘貼代碼,所以我必須有點創意,但這對於練習的目的來說沒關係。

因此,在您的應用程序中,您可能會獲得AppComponent,並致電inject爲您的MyGameActivity。所以我猜這個活動有一些注射領域。我不確定你是否直接在那裏使用OkHttpClient,但我們假設你這樣做。例如:

public class MyGameActivity extends SomeActivity { 
    @Inject 
    OkHttpClient okHttpClient; 
    // ... 
} 

我喜歡想這個的方式如下。匕首知道你需要由AppComponent給出的OkHttpClient。所以它會研究如何提供它 - 它可以建立對象本身,因爲你用@Inject註釋了構造函數嗎?它需要更多的依賴性嗎?

在這種情況下,它將查看提供此客戶端的組件的模塊。它將達到getHttpClient並意識到它需要一個Cache對象。它會再次尋找如何提供這個對象 - 構造函數注入,另一個提供者方法?

它再次在模塊中提供,所以它將達到getNetworkCache並且再次意識到它需要另一個依賴。

此行爲將繼續,直到它達到不需要其他依賴項的對象,例如getEndpoint中的HttpUrl

完成這一切後,您可以創建您的OkHttpClient

我覺得它很容易從這個理解爲什麼你不能有循環在你的依賴關係圖 - 如果它依賴於BB取決於A不能創建一個對象A。所以想象一下,出於某種奇怪的原因,你會達到方法getEndpoint,這取決於該模塊的OkHttpClient。這是行不通的。你會在圈子裏永遠不會結束。

所以,如果我理解你的問題:如何使用整個依賴關係圖而不調用每個單身輪流獲得所需的輸入?

不是。它必須調用所有的方法才能獲得單身人士。至少第一次在相同的組件/範圍內提供它們。之後,只要保持組件的同一實例,範圍依賴關係將始終返回相同的實例。匕首將確保這一點。如果出於某種原因銷燬組件或重新創建組件,則依賴關係不會是相同的實例。更多信息here。事實上,所有範圍都是如此。不僅僅是@Singleton s。

但是,據我所知,你做得對。在創建應用程序時,創建組件並緩存它。之後,每次使用方法component()時,總是返回相同的組件,並且範圍依賴關係始終相同。

+0

我弄明白了,正在使用它。當我在Spring中進行依賴注入時,很難改變我的思維過程,也很難通過實現來自己設置它。那個匕首隻要打一個電話就能做到這一點真的很酷。我給了你一個滿意的答案。 –