2016-06-27 5 views
1

Теперь я изучаю Кинжал 2, и мне так больно объяснять вопрос без кодов, поэтому позвольте мне перечислить все мои модули, компоненты и т.д. первая:Модификация не может быть предоставлена ​​без конструктора @Inject или из метода @ Provides- или @ Produces-annotated


App.class

public class App extends Application { 

private ApiComponent mApiComponent = null; 
private AppComponent mAppComponent = null; 

public ApiComponent getApiComponent() { 
    if (mApiComponent == null) { 
     // Dagger%COMPONENT_NAME% 
     mApiComponent = DaggerApiComponent.builder() 
       // list of modules that are part of this component need to be created here too 
       .appModule(new AppModule(this)) // This also corresponds to the name of your module: %component_name%Module 
       .apiModule(new ApiModule(this)) 
       .build(); 

    } 
    return mApiComponent; 
} 

public AppComponent getAppComponent() { 
    if (mAppComponent == null) { 
     // If a Dagger 2 component does not have any constructor arguments for any of its modules, 
     // then we can use .create() as a shortcut instead: 
     mAppComponent = DaggerAppComponent.builder() 
       .appModule(new AppModule(this)) 
       .build(); 

    } 
    return mAppComponent; 
} 
} 

AppComponent

@Singleton 
@Component(modules = AppModule.class) 
public interface AppComponent { 
    void inject(RetrofitDemo target); 
} 

AppModule

private final Application mContext; 

AppModule(Application context) { 
    mContext = context; 
} 

@Singleton 
@ForApplication 
@Provides 
Application provideApplication() { 
    return mContext; 
} 

@Singleton 
@ForApplication 
@Provides 
Context provideContext() { 
    return mContext; 
} 

ApiComponent

@Singleton 
@Component(dependencies = {AppModule.class},modules = {ApiModule.class}) 
public interface ApiComponent { 
    void inject(RetrofitDemo target); 
} 

APIModule

@Inject 
Context application; 

@Inject 
public ApiModule(Context context){ 
    this.application = context; 
} 

@Provides 
@Singleton 
Gson provideGson() { 
    return new GsonBuilder() 
      // All timestamps are returned in ISO 8601 format: 
      .setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") 
      // Blank fields are included as null instead of being omitted. 
      .serializeNulls() 
      .create(); 
} 


@Provides 
@Singleton 
OkHttpClient provideOkHttpClient() { 
    ... 
} 



@Provides 
@Singleton 
public Retrofit provideRetrofit(Gson gson,OkHttpClient okHttpClient){ 
    return new Retrofit.Builder() 
      .baseUrl(DribbleApi.END_POINT) 
      .addConverterFactory(GsonConverterFactory.create(gson)) 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .client(okHttpClient) 
      .build(); 
} 

И моя деятельность будет выглядеть следующим образом:

@Inject 
Retrofit mRetrofit; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_retrofit_demo); 
    ((App) getApplication()).getApiComponent().inject(this); 
... 

Вот сообщение об ошибке:

Error:(18, 10) : retrofit2.Retrofit cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method. 
retrofit2.Retrofit is injected at com.sinyuk.yuk.RetrofitDemo.mRetrofit 
com.sinyuk.yuk.RetrofitDemo is injected at com.sinyuk.yuk.AppComponent.inject(target) 

Что заставляет меня путать это экземпляр Модифицированная обеспечивается ApiModule , но почему массаж с ошибкой сказал, что он введен в appComponent? И я не могу найти место в коде. T_T, это слишком тяжело, чтобы изучить Кинжал для меня ... Я думаю.


Кроме того, в моем случае я написал dependencies = AppModule.class module = ApiModule.class в AppComponent, и это, похоже, прав я думаю, но если бы я написал module = ({AppComponent.class,ApiComponent.class}), он также работает fine.Anybody может объяснить мне, почему?


Просьба рассмотреть мой код и дать мне несколько советов. Thx заранее!

ответ

4

@ Синюк Здесь можно распаковать, и Кинжал немного сложнее с первого взгляда, но я думаю, что могу помочь. Во-первых, у вас есть концептуальное недоразумение в отношении аннотации @Component. A Component - это интерфейс, который вы определяете, и который Кинжал реализуется посредством генерации кода. Вы определите интерфейс и аннотируете его @Component, а затем вы предоставите набор Module s для кинжала, который будет использоваться в процессе генерации. Модули, которые вы используете, передаются через элемент modules аннотации @Component. Если вы хотите, чтобы один Component разрешил еще один Component для поддержки процесса впрыска, то любые интерфейсы Component, которые вам нужны для использования кинжала при вводе кода, будут переданы через элемент dependencies аннотации @Component.

-

В результате неправилен

@Component(dependencies = AppModule.class module = ApiModule.class`) 

вместо того, чтобы иметь один компонент использовать два модуля написать:

@Component(modules = {ApiModule.class, AppModule.class}) 

или иметь один компонент использовать один модуль и зависеть от другого компонента

@Component(modules = {AppModule.class}, dependencies = {ApiComponent.class}) 

Я надеюсь, что это поможет вам попасть на правильный путь. Дайте мне знать, если у вас есть какие-либо последующие вопросы.

0

Хорошо так что ваша конфигурация должна быть эта

public class App extends Application { 
    private AppComponent mAppComponent = null; 

    public AppComponent getAppComponent() { 
     if (mAppComponent == null) { 
      // If a Dagger 2 component does not have any constructor arguments for any of its modules, 
      // then we can use .create() as a shortcut instead: 
      mAppComponent = DaggerAppComponent.builder() 
       .appModule(new AppModule(this)) 
       .build(); 

     } 
     return mAppComponent; 
    } 
} 

И

@Singleton 
@Component(modules = {AppModule.class, ApiModule.class}) 
public interface AppComponent { 
    void inject(RetrofitDemo target); 
} 

И

@Module 
public class AppModule { 
    private final Application mContext; 

    AppModule(Application context) { 
     mContext = context; 
    } 

    @Provides 
    Application provideApplication() { 
     return mContext; 
    } 

    @Provides 
    Context provideContext() { 
     return mContext; 
    } 
} 

И

@Module 
public class ApiModule { 
    @Provides 
    @Singleton 
    Gson provideGson() { 
      return new GsonBuilder() 
      // All timestamps are returned in ISO 8601 format: 
      .setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") 
      // Blank fields are included as null instead of being omitted. 
      .serializeNulls() 
      .create(); 
    } 


    @Provides 
    @Singleton 
    OkHttpClient provideOkHttpClient() { 
      ... 
    } 



    @Provides 
    @Singleton 
    public Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient){ 
     return new Retrofit.Builder() 
     .baseUrl(DribbleApi.END_POINT) 
     .addConverterFactory(GsonConverterFactory.create(gson)) 
     .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
     .client(okHttpClient) 
     .build(); 
    } 
} 

И

//...Activity 

@Inject 
Retrofit mRetrofit; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_retrofit_demo); 
    ((App) getApplication()).getAppComponent().inject(this); 
... 
Смежные вопросы

 Смежные вопросы