作者:绅(bian)士(tai) | 来源:互联网 | 2023-01-21 09:43
我刚刚开始学习如何使用Dagger,并且已经将我的Backend
连接类转换为自动注入.
该类处理Retrofit并执行网络请求.它曾经有静态方法,但现在它是一个对象,例如:
Backend.fetchPost(context, 42); // old way
mBackend.fetchPost(42); // mBackend is an injected field
上下文用于检索AccountManager
使用我的后端服务器提供OAuth令牌的上下文.现在自动注入.
这在活动和片段中效果很好,但我无法弄清楚如何注入我的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 posts = mBackend.getPosts();
// do stuf with the posts
}
}
所以我知道我应该@#!.inject(this)
在构造函数中调用某个地方,但我不确切地知道我应该怎么做:
在应用程序类上使用静态字段来检索依赖关系图的头部,并让它浏览它直到它可以注入所有字段
创建一个工厂类和接口,如用于活动和片段的接口
别的什么?
关于我的dagger2实现的更多细节:
在Backend
类有一个@Inject
构造函数,所以匕首应该能够构建它,只要它可以得到API和GSON解析器的实例:
@Inject
public Backend(BackendApi api, @UploadGson Gson uploadGson) {
mApi = api;
mUploadGson = uploadGson;
}
该BackendModule
匕首模块具有@Provide
用于方法@UploadGson Gson
的对象,并从依赖关系列表BackendApi
来应用程序类(改型)(通过各种对象,如注射器或记录器)
在BackendModule.class
被引用的modules = {}
应用程序的声明@Component
所以基本上,给定一个应用程序对象,dagger应该能够实例化一个类的对象Backend
,我想将它注入到我的SyncAdapter
类中.
我只是不知道如何实际触发注射.
PS:如上所述,我昨天学会了Dagger,所以请告知你是否认为我的实施已被破坏.
1> Benoit Duffe..:
我想我在这里发帖太快了.我认为框架实例化了我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();
}
}
这是同步适配器:默认构造函数是隐藏的(私有),新构造函数是为Dagger制作的:它直接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 {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder {
}
}
这是引用该子组件的模块.它提供了构造函数(resp.)所期望的SyncService
(并且AuthenticatorService
,它以完全相同的行为实现):SyncAdapter
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
后端,存储库等:应用程序逻辑
服务注入:子组件
也许这可以帮助别人.