0

I'm trying to implement ProgressDialog in Module Class using Dagger2.

My code is like below.

Dagger2DemoApplication.java

public class Dagger2DemoApplication extends Application {

    private ApplicationComponent mApplicationComponent;

    @Override
    public void onCreate() {
        super.onCreate();

        mApplicationComponent = DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule(this))
                .build();
    }

    public ApplicationComponent getmApplicationComponent() {
        return mApplicationComponent;
    }
}

ApplicationModule.java

@Module
public class ApplicationModule {

    private Dagger2DemoApplication mDagger2DemoApplication;

    public ApplicationModule(Dagger2DemoApplication dagger2DemoApplication) {
        this.mDagger2DemoApplication = dagger2DemoApplication;
    }

    @Provides
    @Singleton
    public APIEndPoints provideAPIEndPoints() {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://reqres.in/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        APIEndPoints apiEndPoints = retrofit.create(APIEndPoints.class);

        return apiEndPoints;
    }

    @Provides
    @Singleton
    public Context provideActivityContext() {
        return mDagger2DemoApplication.getApplicationContext();
    }

    @Provides
    @Singleton
    public ProgressDialog provideProgressDialog(Context context) {

        ProgressDialog mProgressDialog = new ProgressDialog(context);

        mProgressDialog.setTitle(context.getString(R.string.str_progress_dialog_title));
        mProgressDialog.setMessage(context.getString(R.string.str_progress_dialog_desc));
        mProgressDialog.setCancelable(false);

        return mProgressDialog;
    }
}

ApplicationComponent.java

@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {

    void inject(BaseActivity baseActivity);
}

BaseActivity.java

public class BaseActivity extends AppCompatActivity {

    @Inject
    protected ProgressDialog mProgressDialog;

    @Inject
    protected HomePresenter homePresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // For Dagger2 i.e Creating instance of all provide methods defined in ApplicationModule
        ((Dagger2DemoApplication) getApplication()).getmApplicationComponent().inject(this);
    }
}

HomeActivity.java

public class HomeActivity extends BaseActivity implements BaseView {

    // Widgets
    @BindView(R.id.rv_users)
    RecyclerView rv_users;

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

        // For ButterKnife
        ButterKnife.bind(this);

        // Initializing Presenter
        homePresenter.attachView(this);
    }

    public void getDataFromServer(View view) {
        mProgressDialog.show();
        homePresenter.callAPI();
    }

    // BaseView Methods
    @Override
    public void handleResponse(Object obj) {
        Users users;
        if (obj instanceof Users) {
            users = (Users) obj;
            if (users != null) {
                mProgressDialog.dismiss();
                rv_users.setLayoutManager(new LinearLayoutManager(HomeActivity.this));
                rv_users.setAdapter(new HomeRVAdapter(users.getData()));
            }
        }
    }

    @Override
    public void showMessage(String msg) {
        if (msg != null) {
            mProgressDialog.dismiss();
            Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
        }
    }
}

I'm getting below error.

01-24 15:09:57.981 10922-10922/com.dagger2demo.dagger2demo E/AndroidRuntime: FATAL EXCEPTION: main
                                                                             Process: com.dagger2demo.dagger2demo, PID: 10922
                                                                             java.lang.IllegalStateException: Could not execute method for android:onClick
                                                                                 at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
                                                                                 at android.view.View.performClick(View.java:5268)
                                                                                 at android.view.View$PerformClick.run(View.java:21550)
                                                                                 at android.os.Handler.handleCallback(Handler.java:822)
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:104)
                                                                                 at android.os.Looper.loop(Looper.java:207)
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:5811)
                                                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
                                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:681)
                                                                              Caused by: java.lang.reflect.InvocationTargetException
                                                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                                                 at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
                                                                                 at android.view.View.performClick(View.java:5268) 
                                                                                 at android.view.View$PerformClick.run(View.java:21550) 
                                                                                 at android.os.Handler.handleCallback(Handler.java:822) 
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:104) 
                                                                                 at android.os.Looper.loop(Looper.java:207) 
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:5811) 
                                                                                 at java.lang.reflect.Method.invoke(Native Method) 
                                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791) 
                                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:681) 
                                                                              Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
                                                                                 at android.view.ViewRootImpl.setView(ViewRootImpl.java:687)
                                                                                 at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:319)
                                                                                 at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
                                                                                 at android.app.Dialog.show(Dialog.java:326)
                                                                                 at com.dagger2demo.dagger2demo.mvp.home.HomeActivity.getDataFromServer(HomeActivity.java:36)
                                                                                 at java.lang.reflect.Method.invoke(Native Method) 
                                                                                 at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
                                                                                 at android.view.View.performClick(View.java:5268) 
                                                                                 at android.view.View$PerformClick.run(View.java:21550) 
                                                                                 at android.os.Handler.handleCallback(Handler.java:822) 
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:104) 
                                                                                 at android.os.Looper.loop(Looper.java:207) 
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:5811) 
                                                                                 at java.lang.reflect.Method.invoke(Native Method) 
                                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791) 
                                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:681)

At looking error, I think ProgressDialog is not getting initialized. I'm new to dagger2. Any help will be appreciated. Thanks in advance.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Maulik Dodia
  • 1,629
  • 2
  • 21
  • 48

1 Answers1

4

You're intitializing your Dialog with an Application Context. It needs an Activity Context, as an Application doesn't have an associated UI.

I'm not sure why you're injecting it via Dagger anyway. Things should be injected via Dagger when they need to be used all over your app and passing it would be difficult, or require you to go through multiple layers. Or when initializing it requires other variables that need to be treated that way. It shouldn't be used just to allocate all your variables. This dialog doesn't meet any of those criteria. There's no good reason to be injecting a Dialog used only in the Activity itself, create it in onCreate instead.

And it ABSOLUTELY should not be a global singleton. Dialogs are owned by the Activity which displays them, sharing one between two Activities will never work. At a minimum it needs to be scoped to an Activity based injection component, but in reality it just shouldn't be injected.

Also, the function you named provideActivityContext doesn't provide the Activity context, it provides the Application context. Fixing that would likely make things not crashed, but you're still misusing Dagger.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • Thank you for all the information. I will be removing `ProgressDialog` injection soon. But I'm unable to return `Activity Context ` in `provideActivityContext` method. There is no method like `getActivityContext` or `getContext`. I tried with `getBaseContext` but it is not working@GabeSechan – Maulik Dodia Jan 24 '18 at 10:20
  • @MaulikDodia The activity Context is the Activity itself. THere's no way to get it from another context, you just need to pass in the activity. – Gabe Sechan Jan 24 '18 at 17:06
  • Thank you for the information. I have some doubts regarding Dagger2. I have asked question [here](https://stackoverflow.com/questions/48380865/dagger2-project-rebuild-error-field-injection-android). Can you just look into it, if you don't mind?@GabeSechan – Maulik Dodia Jan 25 '18 at 06:19