Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eventbus event never gets to the fragment

I have a Fragment A which on a click of a button will start Fragment B that contains a RecyclerView. In Fragment B, on click of an item EventBus is started and that value needs to be passed to Fragment A. But, for some reason, the value never reaches Fragment A.

Fragment A

    public class OrderSummaryFragment extends BaseFragment implements OrderSummaryView {
    private static final String ARG_PARAM1 = "param1";
    public static final String ACTION_BACK = OrderSummaryFragment.class.getName() + ".back";
    public static final String ACTION_HIDE_ACTION_BAR = OrderSummaryFragment.class.getName() + ".hide_action_bar";
    public static final String ACTION_SHOW_ACTION_BAR = OrderSummaryFragment.class.getName() + ".show_action_bar";
    public static final String ACTION_CHANGE_ADDRESS = OrderSummaryFragment.class.getName() + ".select_address";

    FragmentOrderSummaryBinding mBinder;
    Shop mShop;
    OrderSummaryPresenter mPresenter;

    public OrderSummaryFragment() {

    }

    public static OrderSummaryFragment newInstance(Shop shop) {
        OrderSummaryFragment fragment = new OrderSummaryFragment();
        Bundle args = new Bundle();
        args.putParcelable(ARG_PARAM1, Parcels.wrap(shop));
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            Parcelable parcelable;
            parcelable = getArguments().getParcelable(ARG_PARAM1);
            mShop = Parcels.unwrap(parcelable);
        }
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinder = DataBindingUtil.inflate(inflater, R.layout.fragment_order_summary, container, false);
        mPresenter = new OrderSummaryPresenterImpl(this);
        sendActionToActivity(ACTION_HIDE_ACTION_BAR);
        setUIListeners();
        EventBus.getDefault().register(this);
        return mBinder.getRoot();
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mPresenter.loadBillingAddress(mShop);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        sendActionToActivity(ACTION_SHOW_ACTION_BAR);
        EventBus.getDefault().unregister(this);
        mPresenter.cleanup();
    }

    @Override
    protected void setTypeface() {
        mBinder.tvBackButton.setTypeface(FontManager.getInstance().getFontAwesome());
    }

    private void setUIListeners() {
        mBinder.tvBackButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendActionToActivity(ACTION_BACK);
            }
        });
        mBinder.btnChange.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendActionToActivity(ACTION_CHANGE_ADDRESS, mShop);
            }
        });
    }

    @Override
    public void renderBillingAddress(UserInfo userInfo) {
        mBinder.setUserInfo(userInfo);
        if (userInfo.getAddress2().equals("")) {
            mBinder.tvBillingAddress2.setVisibility(View.GONE);
        }
    }

    @Override
    public void renderPaymentTerms(List<PaymentInfo> paymentInfoList) {

    }

    @Override
    public void renderDeliveryMethod(List<DeliveryInfo> deliveryInfoList) {

    }

    @Override
    public void showProgress(boolean show) {

    }

    @Override
    public void showError(Error error) {

    }

    private void sendActionToActivity(String action) {
        if (mListener == null) {
            return;
        }
        Bundle bundle = new Bundle();
        bundle.putString(Constants.ACTION_KEY, action);
        mListener.onFragmentInteraction(bundle);
    }

    private void sendActionToActivity(String action, Shop shop) {
        if (mListener == null) {
            return;
        }
        Bundle bundle = new Bundle();
        bundle.putString(Constants.ACTION_KEY, action);
        bundle.putParcelable(Constants.DATA_KEY_1, Parcels.wrap(shop));
        mListener.onFragmentInteraction(bundle);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessage(ShippingAddressResult event) {
        UserInfo userInfo = event.getUserInfo();
        Log.d("Tag", "Test" + userInfo);
    }
}

Fragment B

    public class ShippingAddressFragment extends BaseFragment implements ShippingAddressView,
        ShippingAddressAdapter.OnItemInteractionListener {
    private static final String ARG_PARAM1 = "param1";
    public static final String ACTION_BACK = ShippingAddressFragment.class.getName() + ".back";
    public static final String ACTION_HIDE_ACTION_BAR = ShippingAddressFragment.class.getName() + ".hide_action_bar";
    public static final String ACTION_SHOW_ACTION_BAR = ShippingAddressFragment.class.getName() + ".show_action_bar";
    public static final String ACTION_NEW_ADDRESS = ShippingAddressFragment.class.getName() + ".new_address";

    FragmentShippingAddressBinding mBinder;
    Shop mShop;
    ShippingAddressAdapter mAdapter;
    ShippingAddressPresenterImpl mPresenter;
    List<UserInfo> mUserInfoList;

    public ShippingAddressFragment() {

    }

    public static ShippingAddressFragment newInstance(Shop shop) {
        ShippingAddressFragment fragment = new ShippingAddressFragment();
        Bundle args = new Bundle();
        args.putParcelable(ARG_PARAM1, Parcels.wrap(shop));
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            Parcelable parcelable;
            parcelable = getArguments().getParcelable(ARG_PARAM1);
            mShop = Parcels.unwrap(parcelable);
        }
        mUserInfoList = new ArrayList<>();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinder = DataBindingUtil.inflate(inflater, R.layout.fragment_shipping_address, container, false);
        setUIListener();
        mPresenter = new ShippingAddressPresenterImpl(this);
        sendActionToActivity(ACTION_HIDE_ACTION_BAR);
        mAdapter = new ShippingAddressAdapter(getContext(), mUserInfoList);
        mAdapter.addOnInteractionListener(this);
        LinearLayoutManager manager = new LinearLayoutManager(getContext());
        mBinder.rvShippingAddress.setLayoutManager(manager);
        mBinder.rvShippingAddress.addItemDecoration(new DividerItemDecoration(getActivity()));
        mBinder.rvShippingAddress.setAdapter(mAdapter);
        return mBinder.getRoot();
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mPresenter.loadShippingAddress(mShop);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mPresenter.cleanup();
        sendActionToActivity(ACTION_SHOW_ACTION_BAR);
        mAdapter.removeInteractionListener();
    }

    @Override
    protected void setTypeface() {
        mBinder.tvBackButton.setTypeface(FontManager.getInstance().getFontAwesome());
    }

    private void setUIListener() {
        mBinder.tvBackButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendActionToActivity(ACTION_BACK);
            }
        });
        mBinder.fabNewAddress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendActionToActivity(ACTION_NEW_ADDRESS, mShop);
            }
        });
    }

    @Override
    public void onClick(UserInfo userInfo) {
        selectedShippingAddress(userInfo);
        sendActionToActivity(ACTION_BACK);
    }

    @Override
    public void renderShippingAddress(List<UserInfo> userInfoList) {
        mUserInfoList.clear();
        mUserInfoList.addAll(userInfoList);
        mAdapter.notifyDataSetChanged();
    }

    private void sendActionToActivity(String action) {
        if (mListener == null) {
            return;
        }
        Bundle bundle = new Bundle();
        bundle.putString(Constants.ACTION_KEY, action);
        mListener.onFragmentInteraction(bundle);
    }

    private void sendActionToActivity(String action, Shop shop) {
        if (mListener == null) {
            return;
        }
        Bundle bundle = new Bundle();
        bundle.putString(Constants.ACTION_KEY, action);
        bundle.putParcelable(Constants.DATA_KEY_1, Parcels.wrap(shop));
        mListener.onFragmentInteraction(bundle);
    }

    private void sendActionToActivity(String action, Shop shop, AllCheckoutInfo allCheckoutInfo) {
        if (mListener == null) {
            return;
        }
        Bundle bundle = new Bundle();
        bundle.putString(Constants.ACTION_KEY, action);
        bundle.putParcelable(Constants.DATA_KEY_1, Parcels.wrap(shop));
        bundle.putParcelable(Constants.DATA_KEY_2, Parcels.wrap(allCheckoutInfo));
        mListener.onFragmentInteraction(bundle);
    }

    @Override
    public void showProgress(final boolean show) {

    }

    @Override
    public void showError(Error error) {

    }

    private void selectedShippingAddress(UserInfo userInfo) {
        ShippingAddressResult event;
        event = new ShippingAddressResult();
        event.setUserInfo(userInfo);
        EventBus.getDefault().post(event);
    }
}
like image 494
Esteban Avatar asked Feb 03 '17 07:02

Esteban


2 Answers

Since you're replacing Fragment A with Fragment B, when the event is fired, Fragment A is not alive/registered to catch it. Regular events look for subscribers the moment they're fired, and then die. If there are any subscribers to that event at that time, they receive the event. This is where Sticky Events come to the rescue. Sticky Events "stick" around. Subscribers subscribing (stickly) to a sticky event after its post moment will still get it. For this do the following.

Replace EventBus.getDefault().post(event); with EventBus.getDefault().postSticky(event);

And make your ShippingAdressResult subscription sticky:

@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onMessage(ShippingAddressResult event) {
    UserInfo userInfo = event.getUserInfo();
    Log.d("Tag", "Test" + userInfo);
    EventBus.getDefault().removeStickyEvent(stickyEvent); // don't forget to remove the sticky event if youre done with it
}

More Info

like image 156
Mehmet K Avatar answered Nov 04 '22 09:11

Mehmet K


I think Sticky Event is what you need. If you don't have any subscriber to consume an event it will wait until it you subscribe. Which may be the your situation as you are replacing fragments.

EventBus.getDefault().postSticky(event);

If you don't need this event anymore, don't forget to remove it.

EventBus.getDefault().removeStickyEvent(stickyEvent);

Good luck!

like image 38
Andrej Jurkin Avatar answered Nov 04 '22 11:11

Andrej Jurkin