Ali Ali - 1 year ago 125
Android Question

Android Dagger 2 and clean architecture implementation, scope errors

I'm trying to figure how to deal with dependency injection with dagger 2 and clean architecture in Android. What i want to achieve is when i click a button, a message will be saved to Firebase Database. And show success message to user. When i build my project i'm getting this error:


Error:(10, 1) error: com.example.mvpsample.home.HomeComponent
(unscoped) may not reference scoped bindings: @Provides @Singleton
com.google.firebase.database.FirebaseDatabase
com.example.mvpsample.data.DataModule.provideFirebaseDatabase()


Here my app class:


public class MyApp extends Application {

private static MyApp app;
private HomeComponent homeComponent;
private AuthenticationComponent authenticationComponent;

@Inject
Presenter presenter;

@Override
public void onCreate() {
super.onCreate();
app = this;

homeComponent = DaggerHomeComponent
.builder()
.homeModule(new HomeModule(presenter.getView()))
.build();
}

public HomeComponent getHomeComponent() {
return homeComponent;
}

public static MyApp app() {
return app;
}
}




HomeActivity


public class HomeActivity extends AppCompatActivity implements BaseContract.View {

@Inject
public Presenter presenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);

MyApp
.app()
.getHomeComponent()
.inject(this);

}

@OnClick(R.id.tvHello)
public void clickTvHello() {
presenter.writeStringToDatabase("Hi");
}


@Override
public void showSuccessMessage() {
Toast.makeText(this, "Success", Toast.LENGTH_SHORT).show();
}
}



HomeModule


@Module
public class HomeModule {

private final BaseContract.View View;

@Inject
public HomeModule(BaseContract.View View) {
this.View = View;
}

@Provides
public BaseContract.View provideView() {
return View;
}
}



HomeComponent


@Component(modules = {HomeModule.class, DataModule.class})
public interface HomeComponent {
void inject(HomeActivity homeActivity);
}



DataModule


@Module
public class DataModule {

@Provides
@Singleton
public FirebaseDatabase provideFirebaseDatabase() {
return FirebaseDatabase.getInstance();
}
}



BaseContract


public interface BaseContract {
interface View {
void showSuccessMessage();
}

interface Presenter {

View getView();

void writeStringToDatabase(String string);
}
}



Presenter


public class Presenter implements BaseContract.Presenter {

private final BaseContract.View View;

@Inject
FirebaseDatabase firebaseDatabase;

@Inject
public Presenter(BaseContract.View View) {
this.View = View;
}


@Override
public BaseContract.View getView() {
return View;
}

@Override
public void writeStringToDatabase(String string) {
firebaseDatabase.getReference()
.child("messages")
.push()
.child("value")
.setValue(string).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
getView().showSuccessMessage();
}
});
}
}



I followed sample projects and tutorials but did not understand what i'm doing wrong here. Not looking for working project but i want to learn what is best practice of this and how to manage and use modules and components.

Answer Source

The problem is that your HomeComponent is not scoped while your DataModule provides a scoped dependency (i.e the FirebaseDatabase dependency).

A non-scoped component cannot rely on scoped provider. You either have to remove the @Singleton on your provideFirebaseDatabase() provider or add @Singleton on your HomeComponent.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download