I have created NetComponent and NetModule where I am initialise all required libs for network communication.
Here is NetComponent code:
#Singleton
#Component(modules={AppModule.class, NetModule.class})
public interface NetComponent {
Retrofit retrofit();
}
I have initalised that NetComponent inside Application class.
public class App extends Application {
private NetComponent mNetComponent;
#Override
public void onCreate() {
super.onCreate();
mNetComponent = DaggerNetComponent.builder()
.appModule(new AppModule(this))
.netModule(new NetModule("mock.com"))
.build();
}
public NetComponent getNetComponent() {
return mNetComponent;
}
}
Now I want to use SharedPreferences inside my application, so I have created SharedPreferencesModule and Component classes.
#Module
public class SharedPreferenceModule {
Application mApplication;
public SharedPreferenceModule(Application mApplication) {
this.mApplication = mApplication;
}
#Provides
#Singleton
Application providesApplication() {
return mApplication;
}
#Provides
#Singleton
SharedPreferences providesSharedPreferences(Application application) {
return PreferenceManager.getDefaultSharedPreferences(application);
}
}
Here is the code from SharedPreferencesComponent:
#Singleton
#Component(modules = {SharedPreferenceModule.class})
public interface SharedPreferenceComponent {
SharedPreferences getSharedPreference();
}
I want to use that inside my LoginAccountFragment class. LoginAccountFragment class has it's own module and component.
#Module
public class LoginAccountModule {
private LoginAccountView view;
public LoginAccountModule(LoginAccountView view){
this.view = view;
}
#Provides
#FragmentScoped
LoginAccountView providesLoginAccountView(){
return view;
}
#Provides
#FragmentScoped
LoginAccountPresenter providesLoginAccountPresenter(LoginAccountPresenterImpl presenter){
return presenter;
}
}
#FragmentScoped
#Component(dependencies = {NetComponent.class}, modules = LoginAccountModule.class)
public interface LoginAccountComponent {
void inject(LoginAccountFragment fragment);
}
How I can inject SharedPreferences in LoginAccountFragment?
#Singleton
#Component(modules={AppModule.class, NetModule.class, SharedPreferenceModule.class})
public interface ApplicationComponent {
Retrofit retrofit();
SharedPreferences sharedPreferences();
}
public class App extends Application {
private ApplicationComponent applicationComponent;
#Override
public void onCreate() {
super.onCreate();
this.applicationComponent = DaggerNetComponent.builder()
.appModule(new AppModule(this))
.netModule(new NetModule("https://mock.com"))
.build();
}
public ApplicationComponent applicationComponent() {
return applicationComponent;
}
}
#Module
public class SharedPreferenceModule {
#Provides
#Singleton
SharedPreferences providesSharedPreferences(Application application) {
return PreferenceManager.getDefaultSharedPreferences(application);
}
}
#Module
public class LoginAccountModule {
private LoginAccountView view;
public LoginAccountModule(LoginAccountView view){
this.view = view;
}
#Provides
LoginAccountView loginAccountView(){
return view;
}
#Provides
#FragmentScoped
LoginAccountPresenter loginAccountPresenter(LoginAccountPresenterImpl presenter) {
return presenter;
}
}
#FragmentScoped
#Component(dependencies = {ApplicationComponent.class}, modules = LoginAccountModule.class)
public interface LoginAccountComponent extends ApplicationComponent {
void inject(LoginAccountFragment fragment);
}
Related
I am trying to learn Dagger2 from this medium article and pass RequestQueue as an activity level dependency:
https://proandroiddev.com/dagger-2-annotations-binds-contributesandroidinjector-a09e6a57758f
I can create application components just fine but I am facing a lot of trouble with ContributesAndroidInjector.
Application Class:
public class PokemonApplication extends Application {
private static AppComponent appComponent;
public static AppComponent getAppComponent(){
return appComponent;
}
#Override
public void onCreate() {
super.onCreate();
appComponent=buildMyComponent();
}
private AppComponent buildMyComponent() {
return DaggerAppComponent.builder().appmod(this).build();
}
}
AppModule:
#Module
public abstract class AppModule {
#ContributesAndroidInjector(modules = VolleyModule.class)
abstract MainActivity mainActivity();
#Provides
#Singleton
static SharedPreferences providePreferences(Application application) {
return application.getSharedPreferences("data", Context.MODE_PRIVATE);
}
#Provides
#Singleton
static Context getContext(Application application){
return application.getApplicationContext();
}
}
AppComponent:
#Singleton
#Component(modules = {RetrofitModule.class,AppModule.class})
public interface AppComponent {
void inject(MainActivity mainActivity); //Error here.
#Component.Builder
interface Builder
{
AppComponent build();
#BindsInstance Builder appmod(Application application);
}
}
VolleyModule:
#Module
public abstract class VolleyModule {
#Provides
static RequestQueue getRequestQueue(Context context) {
return Volley.newRequestQueue(context);
}
}
MainActivity:
#Inject
RequestQueue requestQueue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PokemonApplication.getAppComponent().inject(this);
VolleyModule has to be also declared in the list of modules in your Component
#Singleton
#Component(modules = {RetrofitModule.class,AppModule.class, VolleyModule.class})
I am confused about Dagger2 in Android.
I use two scope. #Singleton, #PerActivity
This is my Code. I simplyfy my code.
//ApplicationComponent.java
#Singleton
#Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
#Named("packageName") String packageName();
}
//ApplicationModule.java
#Module
public class ApplicationModule {
#Provides
#Singleton
public Context provideApplicationContext() {
return MyApplication.getContext();
}
#Provides
#Singleton
#Named("packageName")
public String providePackageName(Context context) {
return context.getPackageName();
}
}
//UserComponent.java
#PerActivity
#Component(modules = {UserModule.class})
public interface UserComponent {
void inject(MainActivity activity);
}
//UserModule.java
#Module
public class UserModule {
String packageName;
public UserModule(String packageName) {
this.packageName = packageName;
}
#Provides
#PerActivity
UserRepositoryImpl provideUserRepositoryImpl() {
return new UserRepositoryImpl(packageName);
}
}
for inject appVersion, packagename in UserModule
DaggerChatComponent.builder()
.userModule(new UserModule(getApplicationComponent().packageName()))
.build();
but it looks not great. how can i inject when use different Scope??
your ApplicationModule.java is correct
#Module
public class ApplicationModule {
private Application application;
public ApplicationModule(Application application){
this.application = application;
}
#Provides
#Singleton
Context provideContext(){
return application;
}
#Provides
#Singleton
#Named("packagename")
public String providePackageName(Context context) {
return context.getPackageName();
}
}
and it's component class is also right ApplicationComponent.java
#Singleton
#Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
#Named("packagename") String providepackagename();
}
but in the UserModule.java you need not pass the package name object , dagger's object graph does this for you.
#Module
public class UserModule {
public UserModule() {
}
#Provides
#PerActivity
UserRepositoryImpl provideUserRepositoryImpl(#Named("packagename") String packageName) {
return new UserRepositoryImpl(packageName);
}
}
and the next step is while writing the component class for this module add the application component as a dependency ie, your UserComponent.java looks like this
#PerActivity
#Component(dependencies = {ApplicationComponent.class},modules = {UserModule.class})
public interface UserComponent {
void inject(MainActivity mainActivity);
}
with the activity scope as PerActivity.lava
#Scope
#Retention(RetentionPolicy.RUNTIME)
public #interface PerActivity {
}
with this example UserRepositoryImpl.java as
class UserRepositoryImpl {
private String packagename;
public UserRepositoryImpl(String packagename){
this.packagename = packagename;
}
String getPackagename(){
return packagename;
}
}
you can finally inject this in your activity.(MainActivity.java)
public class MainActivity extends AppCompatActivity {
#Inject
UserRepositoryImpl userRepository;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ApplicationComponent component=DaggerApplicationComponent.builder().applicationModule(new ApplicationModule(getApplication())).build();
UserComponent userComponent=DaggerUserComponent.builder().applicationComponent(component).userModule(new UserModule()).build();
userComponent.inject(this);
Log.e("name"," "+userRepository.getPackagename());
}
}
How can I provide activity context in mainModule class ? Thanks! The code looks like this:
#Singleton
#Component(modules = {AndroidInjectionModule.class, AppModule.class, ActivityBuilder.class})
public interface AppComponent {
#Component.Builder
interface Builder {
#BindsInstance
Builder application(Application application);
AppComponent build();
}
void inject(MvmApp app);
}
Activtity builder:
#Module
public abstract class ActivityBuilder {
#ContributesAndroidInjector(modules = {MainModule.class})
abstract MainActivity bindMainActivity();
}
And I have an appModule, and a module for each activity:
#Module
public class AppModule {
#Provides
#Singleton
#ApplicationContext
Context provideContext(Application application) {
return application;
}
#Provides
#Singleton
DataManager provideDataManager(AppDataManager appDataManager) {
return appDataManager;
}
#Provides
#DatabaseInfo
String provideDatabaseName() {
return "carDatabase";
}
#Provides
#Singleton
AppDataBase provideAppDatabase(#DatabaseInfo String dbName, #ApplicationContext Context context) {
return Room.databaseBuilder(context, AppDataBase.class, dbName)
.build();
}
#Provides
#Singleton
DbHelper provideDbHelper(AppDbHelper appDbHelper) {
return appDbHelper;
}
}
AppClass:
public class MvmApp extends Application implements HasActivityInjector {
#Inject
DispatchingAndroidInjector<Activity> activityDispatchingAndroidInjector;
#Override
public void onCreate() {
super.onCreate();
DaggerAppComponent.builder()
.application(this)
.build()
.inject(this);
}
#Override
public DispatchingAndroidInjector<Activity> activityInjector() {
return activityDispatchingAndroidInjector;
}
}
All my activities extends a base activity which inject the Dagger dependecies.
public abstract class BaseActivity extends AppCompatActivity implements MvpView {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidInjection.inject(this);
}
}
In mainModule I need to provide the context of the activity.
#Module
public class MainModule {
#Provides
MainMvpPresenter<MainMvpView> provideMainPresenter(
MainPresenter<MainMvpView> presenter) {
return presenter;
}
#Provides
CompositeDisposable provideCompositeDisposable() {
return new CompositeDisposable();
}
#Provides
CarAdapter provideCarAdapter( #ActivityContext Context context) {
return new CarAdapter(context);
}
}
The solution was:
#Module
public class MainModule {
#Provides
MainMvpPresenter<MainMvpView> provideMainPresenter(
MainPresenter<MainMvpView> presenter) {
return presenter;
}
#Provides
CompositeDisposable provideCompositeDisposable() {
return new CompositeDisposable();
}
#Provides
CarAdapter provideCarAdapter(MainActivity activity) {
return new CarAdapter(activity);
}
}
For people facing a similar issue, I've made a project with Kotlin, and the new android-dagger extension with a lengthy explanation on how things work over here: https://github.com/Obaied/BareBonesAndroidDagger
I have two module, AppModule and SplashViewModule
For AppModule:
#Module
public final class AppModule {
#NonNull
private final MyApplication mApp;
public AppModule(#NonNull MyApplication app) {
mApp = app;
}
#Provides
public Context provideAppContext() {
return mApp;
}
#Provides
public MyApplication provideApp() {
return mApp;
}
#Singleton
#Provides
public UserManager provideUserManager() {
return new UserManager();
}
}
For SplashviewModule
#Module
public final class SplashViewModule {
#Inject
UserManager mUserManager;
#Provides
public SplashInteractor provideInteractor() {
return new SplashInteractorImpl(mUserManager);
}
#Provides
public PresenterFactory<SplashPresenter> providePresenterFactory(#NonNull final SplashInteractor interactor) {
return new PresenterFactory<SplashPresenter>() {
#NonNull
#Override
public SplashPresenter create() {
return new SplashPresenterImpl(interactor);
}
};
}
}
And I inject these to my activity like this:
#Override
protected void setupComponent(#NonNull AppComponent parentComponent) {
DaggerSplashViewComponent.builder()
.appComponent(parentComponent)
.splashViewModule(new SplashViewModule())
.build()
.inject(this);
}
But this does not work. The UserManager would be null. How can I get the singleton instance of UserManager created by AppModule and inject it to SplashViewModule?
You don't have to declare UserManager mUserManager; in SplashViewModule. Just add a UserManager parameter for the method provideInteractor.
#Provides
public SplashInteractor provideInteractor(UserManager userManager) {
return new SplashInteractorImpl(userManager);
}
Can someone help me to resolve this issue, I'm trying to add dagger2 to my application getting this scope issue.
Error:(14, 1) error: com.bmx.presentation.authentication.login.LoginComponent depends on scoped components in a non-hierarchical scope ordering:
#com.bmx.di.scope.ActivityScope com.bmx.data.remote.AuthenticationRepositoryComponent
#com.bmx.di.scope.ActivityScope com.bmx.presentation.authentication.login.LoginComponent
#Module
public class AppModule {
private Application mApplication;
public AppModule(Application mApplication) {
this.mApplication = mApplication;
}
#Provides
#Singleton
Application provideApplication() {
return mApplication;
}
#Provides
#Singleton
public Resources provideResources(Context context) {
return context.getResources();
}
}
---------------------------------
#Module
public class NetModule {
String mBaseUrl;
public NetModule(String mBaseUrl) {
this.mBaseUrl = mBaseUrl;
}
#Provides
#Singleton
Cache provideHttpCache(Application application) {
int cacheSize = 10 * 1024 * 1024;
Cache cache = new Cache(application.getCacheDir(), cacheSize);
return cache;
}
#Provides
#Singleton
Gson provideGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
return gsonBuilder.create();
}
#Provides
#Singleton
OkHttpClient provideOkhttpClient(Cache cache) {
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.cache(cache);
return client.build();
}
#Provides
#Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(mBaseUrl)
.client(okHttpClient)
.build();
}
#Provides
#Singleton
public BmxRestService provideBmxRestService(Retrofit retrofit) {
return retrofit.create(BmxRestService.class);
}
}
---------------------------------------------
#Singleton
#Component(modules = {NetModule.class,AppModule.class})
public interface ApiComponent {
BmxRestService getBmxRestService();
Application getApplication();
}
-----------------------------------------------------
public interface AuthenticationRepository {
Observable<List<UserProfile>> doLogin(String userName, String password);
Observable<List<UserProfile>> doSignUp(String firstName, String lastName,String email,String password);
}
--------------------------------------------------------------
public class AuthenticationRepositoryImpl implements AuthenticationRepository {
private BmxRestService BmxRestService;
#Inject
public AuthenticationRepositoryImpl(#NonNull final BmxRestService BmxRestService) {
this.BmxRestService = BmxRestService;
}
//implementation
}
-------------------------------------------
#ActivityScope
#Module
public class AuthenticationRepositoryModule {
#Provides
#ActivityScope
public AuthenticationRepository provideAuthenticationRepository(BmxRestService BmxRestService) {
return new AuthenticationRepositoryImpl(BmxRestService);
}
}
-----------------------------
#ActivityScope
#Component(modules = {AuthenticationRepositoryModule.class},dependencies = ApiComponent.class)
public interface AuthenticationRepositoryComponent {
AuthenticationRepository getAuthenticationRepository();
}
-----------------------------------
#Module
public class LoginPresenterModule {
private final LoginContract.View mView;
public LoginPresenterModule(LoginContract.View mView) {
this.mView = mView;
}
#Provides
#ActivityScope
LoginContract.View provideLoginContractView(){
return this.mView;
}
}
----------------------------------------------
#ActivityScope
#Component(dependencies = AuthenticationRepositoryComponent.class, modules = LoginPresenterModule.class)
public interface LoginComponent {
void inject(LoginActivity activity);
}
----------------------------------------
public class LoginPresenter extends BasePresenter<LoginContract.View> implements LoginContract.Presenter{
private Scheduler mainScheduler, ioScheduler;
private AuthenticationRepository mAuthenticationRepository;
#Inject
public LoginPresenter(#NonNull final AuthenticationRepository authenticationRepository,#NonNull final LoginContract.View loginView) {
super(loginView);
this.mView =loginView;
this.mAuthenticationRepository =authenticationRepository;
this.mainScheduler = AndroidSchedulers.mainThread();
this.ioScheduler = Schedulers.io();
}
//implementation
}
----------------------
public class LoginActivity extends AppCompatActivity implements LoginContract.View {
private static final String TAG = "LoginActivity";
#Inject
LoginPresenter mLoginPresenter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
}
}
-----------------------
public class BmxApp extends Application {
private ApiComponent apiComponent;
#Override
public void onCreate() {
super.onCreate();
initializeNetComponent();
}
private void initializeNetComponent() {
apiComponent = DaggerApiComponent.builder().netModule(new NetModule(BuildConfig.BASEURL)).appModule(new AppModule(this)).build();
}
public ApiComponent getApiComponent() {
return apiComponent;
}
}
---------------
#Documented
#Scope
#Retention(RetentionPolicy.RUNTIME)
public #interface ActivityScope {
}