Dagger Dagger-MissingBinding]
Posted
技术标签:
【中文标题】Dagger Dagger-MissingBinding]【英文标题】: 【发布时间】:2021-12-13 12:11:36 【问题描述】:这段代码有问题,我找不到。
错误
/home/dashwood/androidStudioProjects/DaggerTest2/app/src/main/java/com/dashwood/daggertest/extra/ApplicationComponent.java:16: error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends android.app.Activity>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.app.Activity>>> cannot be provided without an @Provides-annotated method.
public interface ApplicationComponent
^
java.util.Map<java.lang.Class<? extends android.app.Activity>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.app.Activity>>> is injected at
com.dashwood.daggertest.di.ActivityInjector(activityInjectors)
com.dashwood.daggertest.di.ActivityInjector is injected at
com.dashwood.daggertest.extra.A.activityInjector
com.dashwood.daggertest.extra.A is injected at
com.dashwood.daggertest.extra.ApplicationComponent.inject(com.dashwood.daggertest.extra.A)
ActivityInjector.java
public class ActivityInjector
private final Map<String, AndroidInjector<? extends Activity>> cache = new HashMap<>();
private Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>> activityInjectors;
@Inject
ActivityInjector(Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>> activityInjectors)
this.activityInjectors = activityInjectors;
void inject(Activity activity)
if (!(activity instanceof BaseActivity))
throw new IllegalArgumentException("Activity must extends BaseActivity");
String instanceId = ((BaseActivity) activity).getInstanceId();
if (cache.containsKey(instanceId))
//noinspection unchecked
((AndroidInjector<Activity>) cache.get(instanceId)).inject(activity);
return;
//noinspection unchecked
AndroidInjector.Factory<Activity> injectorFactory =
(AndroidInjector.Factory<Activity>) activityInjectors.get(activity.getClass()).get();
AndroidInjector<Activity> injector = injectorFactory.create(activity);
cache.put(instanceId, injector);
injector.inject(activity);
void clear(Activity activity)
if (!(activity instanceof BaseActivity))
throw new IllegalArgumentException("Activity must extends BaseActivity");
cache.remove(((BaseActivity) activity).getInstanceId());
static ActivityInjector get(Context context)
return ((A) (context.getApplicationContext())).getActivityInjector();
ActivityScope.java
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope
ControllerKey.java
@MapKey
@Target(ElementType.METHOD)
public @interface ControllerKey
Class<? extends Controller> value();
Injector.java
public class Injector
private Injector()
public static void inject(Activity activity)
ActivityInjector.get(activity).inject(activity);
public static void clearComponent(Activity activity)
ActivityInjector.get(activity).clear(activity);
public static void inject(Controller controller)
ScreenInjector.get(controller.getActivity()).inject(controller);
public static void clearComponent(Controller controller)
ScreenInjector.get(controller.getActivity()).clear(controller);
MainScreenBindingModule.java
@Module(subcomponents =
TrendingReposComponent.class,
)
public abstract class MainScreenBindingModule
@Binds
@IntoMap
@ControllerKey(TrendingReposController.class)
abstract AndroidInjector.Factory<? extends Controller> bindingTrendingReposInjector(TrendingReposComponent.builder builder);
ScreenInjector.java
@ActivityScope
public class ScreenInjector
private final Map<Class<? extends Controller>, Provider<AndroidInjector.Factory<? extends Controller>>> screenInjector;
private final Map<String, AndroidInjector<Controller>> cache = new HashMap<>();
@Inject
ScreenInjector(Map<Class<? extends Controller>, Provider<AndroidInjector.Factory<? extends Controller>>> screenInjector)
this.screenInjector = screenInjector;
void inject(Controller controller)
if (!(controller instanceof BaseController))
throw new IllegalArgumentException("Controller must extends BaseController");
String instanceId = controller.getInstanceId();
if (cache.containsKey(instanceId))
Objects.requireNonNull(cache.get(instanceId)).inject(controller);
return;
//noinspection unchecked
AndroidInjector.Factory<Controller> injectFactory =
(AndroidInjector.Factory<Controller>) Objects.requireNonNull(screenInjector.get(controller.getClass())).get();
AndroidInjector<Controller> injector = injectFactory.create(controller);
cache.put(instanceId, injector);
injector.inject(controller);
void clear(Controller controller)
if (!(controller instanceof BaseController))
throw new IllegalArgumentException("Controller must extends BaseController");
cache.remove(controller.getInstanceId());
static ScreenInjector get(Activity activity)
if (!(activity instanceof BaseActivity))
throw new IllegalArgumentException("Controller must be hosted BaseActivity");
return ((BaseActivity) activity).getScreenInjector();
ScreenScope.java
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ScreenScope
A.java
public class A extends Application
@Inject
ActivityInjector activityInjector;
private ApplicationComponent component;
@Override
public void onCreate()
super.onCreate();
component = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
component.inject(this);
public ActivityInjector getActivityInjector()
return activityInjector;
ActivityScreenBinding.java
@Module(subcomponents =
MainActivityComponent.class,
)
public abstract class ActivityBindingModule
@Binds
@IntoMap
@ClassKey(MainActivity.class)
abstract AndroidInjector.Factory<? extends Activity> provideMainActivtyInjector(MainActivityComponent.Builder builder);
ApplicationComponent.java
@Singleton
@Component(modules =
ApplicationModule.class,
ActivityBindingModule.class,
)
public interface ApplicationComponent
void inject(A myApplication);
ApplicationModule.java
@Module
public class ApplicationModule
private final Application application;
public ApplicationModule(Application application)
this.application = application;
@Provides
Context provideApplicationContext()
return application;
BaseActivity.java
public abstract class BaseActivity extends AppCompatActivity
@Inject
ScreenInjector screenInjector;
@Inject
ScreenNavigator screenNavigator;
private static final String INSTANCE_ID_KEY = "instance_id";
private String instanceId;
private Router router;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
if (savedInstanceState != null)
instanceId = savedInstanceState.getString(INSTANCE_ID_KEY);
else
instanceId = UUID.randomUUID().toString();
Injector.inject(this);
ViewGroup screenContainer = findViewById(R.id.screen_container);
if (screenContainer == null)
throw new IllegalArgumentException("Activity must have a view name 'screen_container'");
router = Conductor.attachRouter(this, screenContainer, savedInstanceState);
screenNavigator.initWithRouter(router, initialScreen());
setContentView(layoutRes());
monitorBackStack();
super.onCreate(savedInstanceState);
super.onBackPressed();
@LayoutRes
protected abstract int layoutRes();
@Override
protected void onSaveInstanceState(@NonNull Bundle outState)
super.onSaveInstanceState(outState);
outState.putString(INSTANCE_ID_KEY, instanceId);
public String getInstanceId()
return instanceId;
protected abstract Controller initialScreen();
@Override
public void onBackPressed()
if (!screenNavigator.pop()) super.onBackPressed();
@Override
protected void onDestroy()
super.onDestroy();
screenNavigator.clear();
if (isFinishing())
Injector.clearComponent(this);
public ScreenInjector getScreenInjector()
return screenInjector;
private void monitorBackStack()
router.addChangeListener(new ControllerChangeHandler.ControllerChangeListener()
@Override
public void onChangeStarted(@Nullable Controller to, @Nullable Controller from, boolean isPush, @NonNull ViewGroup container, @NonNull ControllerChangeHandler handler)
@Override
public void onChangeCompleted(@Nullable Controller to, @Nullable Controller from, boolean isPush, @NonNull ViewGroup container, @NonNull ControllerChangeHandler handler)
if (!isPush && from != null)
Injector.clearComponent(from);
);
BaseController.java
public abstract class BaseController extends Controller
private boolean isInjected = false;
@Override
protected void onContextAvailable(@NonNull Context context)
if (!isInjected)
Injector.inject(this);
isInjected = true;
super.onContextAvailable(context);
MainActivityComponent.java
@ActivityScope
@Subcomponent(modules =
MainScreenBindingModule.class,
NavigationModule.class,
)
public interface MainActivityComponent extends AndroidInjector<MainActivity>
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MainActivity>
@Override
public void seedInstance(MainActivity instance)
TrendingReposComponent.java
@ScreenScope
@Subcomponent
public interface TrendingReposComponent extends AndroidInjector<TrendingReposController>
@Subcomponent.Builder
abstract class builder extends AndroidInjector.Builder<TrendingReposController>
TrendingReposController.java
public class TrendingReposController extends BaseController
@NonNull
@Override
protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container, @Nullable Bundle savedViewState)
return null;
DefaultScreenNavigator.java
@ActivityScope
public class DefaultScreenNavigator implements ScreenNavigator
private Router router;
@Inject
DefaultScreenNavigator()
@Override
public void initWithRouter(Router router, Controller rootScreen)
this.router = router;
if (router.hasRootController())
return;
router.setRoot(RouterTransaction.with(rootScreen));
@Override
public boolean pop()
return router!=null && router.handleBack();
@Override
public void clear()
router = null;
NavigationModule.java
@Module
public abstract class NavigationModule
@Binds
abstract ScreenNavigator provideScreenNavigator(DefaultScreenNavigator screenNavigator);
ScreenNavigator.java
public interface ScreenNavigator
void initWithRouter(Router router, Controller rootScreen);
boolean pop();
void clear();
MainActivity.java
public class MainActivity extends BaseActivity
@Override
protected int layoutRes()
return R.layout.activity_main;
@Override
protected Controller initialScreen()
return new TrendingReposController();
Gradle
dependencies
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'com.google.dagger:dagger:2.39.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.39.1'
implementation 'com.google.dagger:dagger-android:2.39.1'
implementation 'com.google.dagger:dagger-android-support:2.39.1'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.39.1'
implementation "com.squareup.retrofit2:retrofit:2.7.1"
implementation "com.squareup.retrofit2:converter-moshi:2.7.1"
implementation "com.squareup.moshi:moshi:1.12.0"
annotationProcessor("com.ryanharter.auto.value:auto-value-moshi-extension:1.1.0")
implementation("com.ryanharter.auto.value:auto-value-moshi-runtime:1.1.0")
annotationProcessor("com.ryanharter.auto.value:auto-value-moshi-factory:1.1.0")
annotationProcessor "com.google.auto.value:auto-value:1.8.2"
implementation 'io.reactivex.rxjava3:rxjava:3.0.3'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'com.jakewharton.rxrelay3:rxrelay:3.0.1'
implementation 'com.bluelinelabs:conductor:3.1.1'
【问题讨论】:
【参考方案1】:我修复了这个错误,因为 AndroidInjector.factory 不能扩展任何类。之后我看到了许多错误并修复了所有错误,您可以从我的 GitHub 看到修复此代码
https://github.com/dashwood01/Dagger-Test
【讨论】:
以上是关于Dagger Dagger-MissingBinding]的主要内容,如果未能解决你的问题,请参考以下文章