2

我剛開始學習如何使用Dagger,並且我已將自己的Backend連接類轉換爲自動注入。如何注入SyncAdapter

該類處理Retrofit並執行網絡請求。它曾經有過的靜態方法,但現在它是一個對象,例如:

Backend.fetchPost(context, 42); // old way 
mBackend.fetchPost(42); // mBackend is an injected field 

上下文用於檢索提供OAuth令牌與我的後端服務器的AccountManager。這現在被自動注入。

在活動和片段中效果很好,但我無法弄清楚如何注入我的SyncAdapter類。
事實上,它是一個我無法控制的框架對象,並且AndroidInjections沒有準備好注入這種類的靜態方法。

下面是我想獲得工作的代碼:

/** 
* Handle the transfer of data between the backend and the app, using the Android sync adapter framework. 
*/ 
public class SyncAdapter extends AbstractThreadedSyncAdapter {  
    @Inject 
    public Backend mBackend; // can't use constructor injection, 
          // so might aswell use a public field 

    public SyncAdapter(Context context, boolean autoInitialize) { 
     super(context, autoInitialize); 
    } 

    public SyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) { 
     super(context, autoInitialize, allowParallelSyncs); 
    } 

    @Override 
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) { 
     List<Post> posts = mBackend.getPosts(); 
     // do stuf with the posts 
    } 
} 

所以我知道我應該在構造函數中調用某個地方@#!.inject(this),但我完全不知道我應該如何做到這一點:

  • 使用的應用程序類的靜態字段檢索依賴圖的頭,讓它瀏覽它,直到它可以注入的所有字段
  • 創建一個工廠類和接口,如FO使用的一個r活動和片段
  • 別的東西?

更多關於我的dagger2實現細節:

  • Backend類有一個@Inject構造,所以匕首應該能夠構建它,只要它可以得到API和GSON解析器的實例:

    @Inject 
    public Backend(BackendApi api, @UploadGson Gson uploadGson) { 
        mApi = api; 
        mUploadGson = uploadGson; 
    } 
    
  • BackendModule匕首模塊具有@Provide方法用於@UploadGson Gson對象,並從依賴關係列表一個BackendApi(改型)到應用程序類(通過各種對象,如注射器或記錄器)
  • BackendModule.classmodules = {}聲明本申請的@Component

所以基本上被引用時,給定的應用對象,匕首應能夠實例化類Backend的對象,我想將其注入到我的SyncAdapter類中。
我只是不知道如何實際觸發注射。 PS:如上所述,我昨天學了匕首,所以請告訴我,如果你認爲我的執行被破壞了,

回答

2

我想我在這裏過得太快。我認爲,框架實例化我SyncAdapter,但是我在做我自己:

public class SyncService extends Service { 
    private static final Object sSyncAdapterLock = new Object(); 

    private static SyncAdapter sSyncAdapter = null; 

    /** 
    * Instantiate the sync adapter object. 
    */ 
    @Override 
    public void onCreate() { 
     synchronized (sSyncAdapterLock) { 
      if (sSyncAdapter == null) { 
       sSyncAdapter = new SyncAdapter(getApplicationContext(), true); // bingo! 
      } 
     } 
    } 

    /** 
    * Return an object that allows the system to invoke the sync adapter. 
    */ 
    @Override 
    public IBinder onBind(Intent intent) { 
     return sSyncAdapter.getSyncAdapterBinder(); 
    } 
} 

所以我只需要注入的服務,我完成了。以下是如何解決這個問題:

public class SyncService extends Service { 
    @Inject 
    SyncAdapter sSyncAdapter; 

    /** 
    * Instantiate the sync adapter object. 
    */ 
    @Override 
    public void onCreate() { 
     AndroidInjection.inject(this); 
    } 

    /** 
    * Return an object that allows the system to invoke the sync adapter. 
    */ 
    @Override 
    public IBinder onBind(Intent intent) { 
     return sSyncAdapter.getSyncAdapterBinder(); 
    } 
} 

這裏的同步適配器:默認的構造函數隱藏(不公開)和新的構造方法制作的匕首:它直接SyncService預計爲背景和注入後端和其他對象(在我的情況下,一個存儲庫類)。

public class SyncAdapter extends AbstractThreadedSyncAdapter { 
    private static final String TAG = SyncAdapter.class.getSimpleName(); 

    private Backend mBackend; 

    private PostRepository mRepository; 

    @Inject 
    SyncAdapter(SyncService service, Backend backend, PostRepository repo) { 
     this(service, true); 
     mBackend = backend; 
     mRepository = repo; 
    } 

    private SyncAdapter(Context context, boolean autoInitialize) { 
     super(context, autoInitialize); 
    } 

新的子組件的服務注入:

@Subcomponent(modules = {}) 
public interface SyncServiceSubcomponent extends AndroidInjector<SyncService> { 
    @Subcomponent.Builder 
    abstract class Builder extends AndroidInjector.Builder<SyncService> { 
    } 
} 

下面是引用子模塊。它提供了SyncService(和AuthenticatorService,這是完全相同的行爲實施)由SyncAdapter構造(RESP Authenticator)預計:

/** 
* Used to provide/bind services with a factory 
* Services can't be injected in the constructor so this is required 
*/ 
@Module(subcomponents = { 
     SyncServiceSubcomponent.class, 
     AuthenticatorServiceSubcomponent.class, 
}) 
public abstract class ServicesModule { 
    @Binds 
    @IntoMap 
    @ServiceKey(SyncService.class) 
    abstract AndroidInjector.Factory<? extends Service> bindSyncServiceInjectorFactory(SyncServiceSubcomponent.Builder builder); 

    @Binds 
    @IntoMap 
    @ServiceKey(AuthenticatorService.class) 
    abstract AndroidInjector.Factory<? extends Service> bindAuthenticatorServiceInjectorFactory(AuthenticatorServiceSubcomponent.Builder builder); 
} 

所以同步適配器具有以下依存關係:

  • 同步服務:由ServicesModule提供
  • 後端,存儲庫等:應用程序邏輯
  • 服務注入:子組件

也許這可以幫助某人。