Как получить экземпляр Activity в классе Module с помощью AndroidInjector? - PullRequest
1 голос
/ 01 июля 2019

У меня есть пример проекта, в котором я использую AndroidInjector dagger-android, чтобы ввести зависимости. В этом примере приложения у меня есть класс Navigator, который выполняет всю навигацию «Активность в активность» и требует наличия экземпляра текущего Activity в своем конструкторе.

У меня есть класс AppModule, который предоставляет экземпляры другому компоненту, который также отвечает за предоставление экземпляра Navigator моему докладчику, но конструктор Navigator принимает Activity в качестве параметра из AppModule. Как я могу получить доступ к экземпляру действия к конструктору Navigator. Я пытался внедрить экземпляр Activity непосредственно в Navigator, аннотируя переменную-член Activity аннотацией @Inject, но это выдает ошибку при построении проекта.

ошибка: [dagger.android.AndroidInjector.inject (T)] android.app.Activity не может быть предоставлена ​​без конструктора @Inject или метода, аннотированного @ Provides. android.app.Activity вводится в

Я сослался на другой пост SA, но это не помогло с моим запросом, или, может быть, я не понял решения, приведенного там. Ниже приведен пост, за которым я следовал

Как добавить текущую активность в соавтор, используя Dagger 2.11 Android инжектор

Как получить MainActivity внутри модуля с помощью AndroidInjector

Ниже приведен код, который я реализовал:

Application.Java

public class MyApplication extends Application implements HasActivityInjector {

    @Inject
    DispatchingAndroidInjector<Activity> androidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
        DaggerAppComponent
                .builder()
                .application(this)
                .build()
                .inject(this);
    }

    @Override
    public AndroidInjector<Activity> activityInjector() {
        return androidInjector;
    }
}

MainActivity.java

public class MainActivity extends BaseActivity implements BaseView {

    @Inject
    Context application;

    @Inject
    MainPresenter mainPresenter;

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

MyPresenter.Java

public class MyPresenter extends BasePresenter<IActivityView> {

    private final NavigationRouter mNavigationRouter;

    @Inject
    public MyPresenter(Navigator navigatr) {
        mNavigationRouter = navigationRouter;
    }

}

Navigator.Java

//This is how my Navigator is currently.
public class Navigator{

    Activity mActivity;

    @Inject
    public Navigator(Activity activity){
    mActivity = activity;
    }

}

ActivityBuilder.java

@Module
public abstract class ActivityBuilder {

    @ContributesAndroidInjector
    abstract MainActivity bindMainActivity();

    @ContributesAndroidInjector
    abstract LoginActivity bindLoginActivity();
}

AppModule.Java

@Module
public class AppModule {
//How can i have the instance of current activity in this module class.
    @Provides
    @Singleton
    NavigationRouter providesNavigationRouter(Activity activity) {
        //Here I want the instance of current activity
        return new NavigationRouter(activity);
    }
}

AppComponent.Java

@Component(modules = {
        AndroidInjectionModule.class,
        AppModule.class,
        ActivityBuilder.class})
@Singleton
public interface AppComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(Application application);

        AppComponent build();
    }

    void inject(MyApplication application);
}

Любая помощь по этому вопросу будет высоко ценится.

Я обновил фрагмент кода для большей ясности

1 Ответ

1 голос
/ 01 июля 2019

В этом примере приложения у меня есть класс Navigator, который выполняет всю навигацию «Активность в активность» и требует наличия экземпляра текущей активности в конструкторе

Я немного запутался вкак это должно работатьЗначит ли это, что каждый Activity создает свой собственный Navigator?Если действие предоставляется через конструктор, то я не могу думать ни о каком другом способе, который был бы осуществим.

В любом случае, если вы хотите создать Navigator для каждого из ваших действий, тогда ваш кинжалНастройка будет выглядеть следующим образом:

MainActivityModule.java

@Module
public abstract class MainActivityModule {
    @Binds @Named(MainActivity.class.getSimpleName()) abstract Navigator navigator(MainActivity ma);
}

ActivityBuilder.java

@Module
public abstract class ActivityBuilder {
    @ContributesAndroidInjector(modules = MainActivityModule.class) 
    abstract MainActivity bindMainActivity();
}

MainActivity.java

public class MainActivity extends BaseActivity implements BaseView {

    @Inject Navigator navigator; //This will hold a reference to MainActivity

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AndroidInjection.inject(this); //Or AndroidSupportInjection...
    }
}

Редактировать: Я сделал пару замечаний в комментариях, которые показывают класс "Навигатор", который принимает одно действие через егоКонструктор не осуществим.Вместо этого вы можете попробовать это:

@Singleton
public final class Navigator {

    private WeakReference<BaseActivity> ref = null;

    @Inject
    Navigator(){}

    void setForegroundActivity(BaseActivity base) {
        this.ref = new WeakReference<>(base);
    }

    void transitionTo(Class<? extends BaseActivity> next) {
        if(ref == null) return;
        final BaseActivity current = ref.get();
        if(current != null) {
            current.transitionTo(next);
        }
    }
}
public class MyApp extends Application implements Application.ActivityLifecycleCallbacks {

    @Inject Navigator navigate;

//...
   void onActivityResumed(Activity activity) {
        if(activity instanceof BaseActivity) {
            navigate.setForegroundActivity((BaseActivity) activitiy);
        }
    }

}
public class AnExampleClass {

    private final Navigator navigate;

    @Inject
    AnExampleClass(Navigator navigate) {
        this.navigate = navigate;
    }

    //...
    void someMethodRequiringATransition() {
        navigator.transitionTo(AnotherActivity.class);
    }

}
public class AnExampleActivity extends BaseActivity {

    @Override
    public void transitionTo(Class<? extends BaseActivity> next) {
        if(AnotherExampleActivity.class.equals(next)) {
            //Do stuff specific to transitioning to "Another Example Activity"
        }
    }    

}

Я использую WeakReference s, потому что хранение Activity в одиночном коде опасно и эффективно вызывает утечки памяти.Тем не менее, вы можете использовать ActivityLifecycleCallbacks для удаления действий, когда они переходят в «onPause».

...