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
Related
I'm trying to Inject my ToDoRepository to my ToDoDeleteNotificationService and always I get this repository null. I don't know if I have to do another Module more or if I can't do it in a IntentService.
#Module
public class ToDoRepositoryModule {
#Provides
#Singleton
ToDoDatabase provideDatabase(Application application) {
return Room.databaseBuilder(application,
ToDoDatabase.class, "ToDo.db")
.build();
}
#Provides
#Singleton
ToDoDao provideUserDao(ToDoDatabase database) {
return database.toDoDao();
}
#Provides
#Singleton
AppExecutors provideAppExecutors() {
return new AppExecutors();
}
#Provides
#Singleton
ToDoRepository providesToDoRepository(ToDoDao toDoDao, AppExecutors appExecutors) {
return new ToDoRepository(toDoDao, appExecutors);
}
}
-- When my class TodoDeleteNotiricationService is called, I get my todoId byt my repository is null
public class ToDoDeleteNotificationService extends IntentService {
#Inject
ToDoRepository mToDoRepository;
public ToDoDeleteNotificationService() {
super("ToDoDeleteNotificationService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
assert intent != null;
String toDoId = intent.getStringExtra(ToDoNotificationsService.TODO_MODEL_KEY);
mToDoRepository.deleteToDo(toDoId);
}
}
--
#Singleton
#Component(modules = {ToDoRepositoryModule.class,
ActivityBindingModule.class,
AppModule.class,
AndroidSupportInjectionModule.class})
public interface AppComponent extends AndroidInjector<ToDoApplication>{
ToDoRepository getToDoRepository();
#Component.Builder
interface Builder{
#BindsInstance
AppComponent.Builder application(Application application);
AppComponent build();
}
}
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());
}
}
i am trying to inject the activity context inside ImageUtls class:
public class ImageUtls {
private Context mContext;
#Inject
public ImageUtls(#ActivityContext Context context) {
this.mContext = context;
}
}
AppModule:
#Module
public class AppModule {
#Provides
#ActivityContext
Context provideActivityContext(Activity activity) {
return activity;
}
#Provides
#ApplicationContext
Context provideContext(Application application) {
return application;
}
}
ActivityBuilder:
#Module
public abstract class ActivityBuilder {
#ContributesAndroidInjector(modules = {OwnerActivityModule.class})
abstract OwnerActivity bindOwnerActivity();
}
OwnerActivityModule:
#Module
public abstract class OwnerActivityModule {
#Provides
abstract Activity bindActivity(OwnerActivity activity);
}
OwnerActivity injection:
public class OwnerActivity extends BaseActivity {
#Inject
ImageUtls imageUtls;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
AppComponent:
#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(MyApplication application);
}
I am not getting a relevant error about what is going wrong..Can anybody address the issue?
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);
}