Open jiaju-yang opened 8 years ago
Always use the application context since it is a singleton application wide. I don't see any reason to use an activity context, cause that could be dangerous and create leaks.
I believe one of the only places where using an application context will cause issues is if you're inflating any kind of UI such as a dialog. I could be wrong but I don't think the themes will be correct.
@lustigdev Thanks for your reply. I think you are right. Here explains why application context and activity context are different.
And the second answer shows us a picture to compare them:
So I think if you wanna start an activity or show a dialog or inflate a layout, you should use activity context instead of application context. According this I made a small change in my code:
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface ForActivity {
}
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface ForApplication {
}
I wrote two annotations to differentiate activity context and application context. And I use them like below:
@Module
public class ApplicationModule {
private final AndroidApplication application;
public ApplicationModule(AndroidApplication application) {
this.application = application;
}
@Provides
@Singleton
@ForApplication
Context provideApplicationContext() {
return application;
}
...
}
This is how I provide application context in di. Usage is simple, just declare @ForApplication
:
@Singleton
public class Toaster {
private final Context context;
@Inject
public Toaster(@ForApplication Context context) {
if (context == null)
throw new IllegalArgumentException("Context can not be null!");
this.context = context;
}
...
}
Activity context is a bit more complex:
@Module
public class ActivityModule {
private final Activity activity;
public ActivityModule(Activity activity) {
this.activity = activity;
}
@Provides
@ForActivity
Context provideActivityContext() {
return activity;
}
}
@ActivityScope
@Subcomponent(
modules =
{
ActivityModule.class
})
public interface MainComponent {
void inject(MainFragment fragment);
}
When I wanna inject context, I just declare @ForActivity
:
public abstract class BaseFragment<P extends Presenter> extends Fragment {
...
@Inject
@ForActivity
protected Context context;
...
}
public class MainFragment extends BaseFragment<MainPresenter> {
//In this class I can use `context` to show a dialog or start an activity and so on when I need activity instead of application context.
}
Any suggestions are welcome^-^
That's the exact chart I was thinking about, I was just too lazy to go find it. Will have a read here on your writeup! Really appreciate the time, and what a great issues tracker in general for learning more about CLEAN architecture.
@psychesworld awsome! I'm reopening this issue since the information here is very valuable. Great job!
I don't know this is a bug or just my misunderstanding?
Here you have injected an adapter. This adapter has a Context type parameter. Apparently this should be an activity context. Because application context lacks the app theme and so on. But there is no activity context provided in your di. Only application context has been provided.
And I found an activity dependancy provided in ActivityModule.
My question is: Do you replace activity context with application context? Or with an acitivity casted by di automatically? Or this is just a bug?