Как вызвать действие в onAttach с помощью Otto?

Я работаю над приложением, которое использует NavigationDrawer. Различные фрагменты помещаются в представление содержимого MainActivity всякий раз, когда выбирается пункт меню в ящике. Чтобы сообщить MainActivity, что Fragment успешно присоединен, выполняется следующий обратный вызов:

public class CustomFragment extends Fragment {

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        ((MainActivity) activity).onSectionAttached();
    }

}

Поскольку я начал использовать Otto с Dagger в проекте Мне любопытно, как я могу заменить обратный вызов событием .post(), например:

mBus.post(new CustomFragmentAttachedEvent);

Проблема в том, что mBus это null в onAttach(). Он инициализируется в onCreate().

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ((MyApp) getActivity().getApplication()).getObjectGraph().inject(this);
}

Вот пример такого класса Fragment.

Рекомендации:


Вы можете легко попробовать этот пример самостоятельно: создайте новый проект из шаблона NavigationDrawer, доступного в Android Studio, добавьте Dagger и Otto и попробуйте замените упомянутый обратный вызов.


Рабочее решение:


person JJD    schedule 20.05.2014    source источник
comment
Я не могу помочь, но мне просто интересно, почему вы не можете создать ссылку на mBus в действии onCreate или в onInflate фрагмента. Опять же, просто любопытно.   -  person nPn    schedule 20.05.2014
comment
@nPn Я просто следую тому, что сказал Джейк Уортон (слайд 141): вводить в 1_.   -  person JJD    schedule 21.05.2014


Ответы (1)


Вы можете создать поставщика для вашей шины Otto с помощью Dagger следующим образом:

@Module(injects = {
    YourFragment.class, 
    MainActivity.class
},complete = true)    
public class EventBusModule {

    @Provides
    @Singleton
    Bus provideBus() {
        return new Bus();
    }
}

Затем вы регистрируете EventBusModule при создании ObjectGraph. Вы можете создать свой график в Application onCreate():

public class MyApplication extends Application{

    public void onCreate() {
        Object[] modules = new Object[]{new EventBusModule()};
        Injector.init(modules);
    }

}

Вам нужно будет создать Injector с некоторыми статическими методами и ссылкой на ObjectGraph, чтобы вы могли манипулировать им, не имея ссылки на Application. Что-то вроде этого:

public final class Injector {

    private static ObjectGraph objectGraph = null;

    public static void init(final Object... modules) {

        if (objectGraph == null) {
            objectGraph = ObjectGraph.create(modules);
        }
        else {
            objectGraph = objectGraph.plus(modules);
        }

        // Inject statics
        objectGraph.injectStatics();
    }

    public static final void inject(final Object target) {
        objectGraph.inject(target);
    }

    public static <T> T resolve(Class<T> type) {
        return objectGraph.get(type);
    }
}

Затем вы просто используете @Inject в своем Fragment, чтобы позволить Dagger дать вам экземпляр Bus и внедрить Fragment:

public class MyFragment extends Fragment{

    @Inject Bus mBus;

    public void onAttach(){
        Injector.inject(this);
    } 

}
person Emmanuel    schedule 20.05.2014
comment
Вы неправильно поняли вопрос. Интеграция Отто не проблема. В целом это уже работает. - person JJD; 21.05.2014
comment
Я не уверен, что понимаю: вы предлагаете мне опускать ((MyApp) getActivity().getApplication()).getObjectGraph().inject(this); во всех фрагментах, предполагая, что я добавляю @Inject Bus mBus; в каждый фрагмент? Пожалуйста, расширьте свой ответ, чтобы уточнить. - person JJD; 21.05.2014
comment
Да, вы можете избежать этой строки, если вы @Inject Bus в классе Application и вызовете ObjectGraph.inject(this) on it. This works because as soon as you make that call, Dagger will have a reference of a Bus` для использования в любом месте вашего приложения. Мы можем поболтать, если это все еще не имеет смысла. - person Emmanuel; 21.05.2014