如何注入SyncAdapter

问题描述:

我刚开始学习如何使用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:如上所述,我昨天学了匕首,所以请告诉我,如果你认为我的执行被破坏了,

我想我在这里过得太快。我认为,框架实例化我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提供
  • 后端,存储库等:应用程序逻辑
  • 服务注入:子组件

也许这可以帮助某人。