Problem: I am using EventBus by greenrobot to pass some events.
It is working for me unfortunately for the scenario of passing data between two fragments it does not. So the event does not get fired.
Question: Do I misunderstand the concept? Or is there a mistake in my code?
Note: Both Fragments exist at the time of sending the event. One fragment is the parent and the other one the child to display details.
detail fragment:
public class DetailFragment extends Fragment {
(...)
refreshButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
EventBus.getDefault().post(new IntentRefresh());
}
});
(...)
}
EventBus class:
public class IntentRefresh {
public IntentRefresh (){}
public void refreshParent() {
}
}
parent fragment:
public class ParentFragment extends Fragment {
(...)
#Override
public void onPause() {
super.onPause();
EventBus.getDefault().unregister(this);
}
#Override
public void onResume() {
super.onResume();
EventBus.getDefault().register(this);
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void updateList(IntentRefresh intentRefresh) {
Toast.makeText(getActivity(), "LUEEEEPT", Toast.LENGTH_SHORT).show();
}
(...)
}
The Fragment lifecycle is quite a bit more complicated than the Activity lifecycle. I would guess that your onResume() isn't being called how you think it is. I would recommend moving your registering and un registering to the onAttach() and onDetach() methods.
I use #CaseyB's answer. its working for me perfectly.Like below
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
}
#Override
public void onDetach() {
super.onDetach();
EventBus.getDefault().unregister(this);
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(CallbackModel event) {
}
Related
I am using EventBus to send the long value from a fragment to another fragment. I use the following code to do that. But for me, it doesn't work. What did I do wrong?
This is the fragment where I save the data:
#OnClick(R.id.buttonFinishMeeting)
public void onClickButton() {
startActivity(RoutePlanCompleteActivity.newIntent(getContext(), routePlan));
EventBus.getDefault().post(new Long(spentTime));
}
Then the fragment I want to send my data:
#Subscribe
public void onEvent(Long time) {
spentTime = time;
}
#Override
public void onResume() {
super.onResume();
EventBus.getDefault().register(this);
}
#Override
public void onPause() {
super.onPause();
EventBus.getDefault().unregister(this);
}
Replace your subscribe method like this :-
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
---
};
This code has been taken from the official documentation of Eventbus from here. If you have any more trouble, visit this link https://github.com/greenrobot/EventBus
I have an Activity which has a Save details button and a Viewpager which contains 4 fragments. The Fragments contains User details form. Once the Save button is clicked I need to get the data from all fragments and save the details. How to get the data entered by the user in all 4 fragments when Save button is clicked in the activity?
I just worked on an app that had the same use case. In addition, I had to save the data on a back navigation as well. The problem was a bit more difficult that I though it should have been. The problems came from the fact that not all the fragments in the ViewPager are guaranteed to be alive. They either may not have been started yet, or destroyed when the user paged off of them.
To solve the problem, I took inspiration from this blog post about handing back-press events. I had to modify it a bit to allow for any fragments that may be running and not just one.
public abstract class BackHandledFragment extends Fragment {
protected BackHandlerInterface backHandlerInterface;
public abstract String getTagText();
public abstract boolean onBackPressed();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!(getActivity() instanceof BackHandlerInterface)) {
throw new ClassCastException("Hosting activity must implement BackHandlerInterface");
} else {
backHandlerInterface = (BackHandlerInterface) getActivity();
}
}
#Override
public void onResume() {
super.onResume();
backHandlerInterface.addRunningFragment(this);
}
#Override
public void onPause() {
super.onPause();
backHandlerInterface.removeRunningFragment(this);
}
public interface BackHandlerInterface {
public void addRunningFragment(BackHandledFragment backHandledFragment);
public void removeRunningFragment(BackHandledFragment backHandledFragment);
}
}
The Activity implements the interface and tracks the active fragments:
public class EditActivity implements BackHandledFragment.BackHandlerInterface
{
private List<BackHandledFragment> listActiveFragments = new ArrayList<>
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Notify each active fragment that the back was pressed, this will allow
// them to save any data.
for (BackHandledFragment bf : listActiveFragments) {
bf.onBackPressed();
}
}
#Override
public void addRunningFragment(BackHandledFragment backHandledFragment) {
listActiveFragments.add(backHandledFragment);
}
#Override
public void removeRunningFragment(BackHandledFragment backHandledFragment) {
listActiveFragments.remove(backHandledFragment);
}();
}
Each fragment must extend BackHandledFragment:
public class DetailNetworkFragment extends BackHandledFragment {
#Override
public void onPause() {
super.onPause();
EventBus.getDefault().unregister(this);
saveDataFields();
}
#Override
public void onResume() {
super.onResume();
EventBus.getDefault().register(this);
}
#Override
public String getTagText() {
return TAG;
}
#Override
public boolean onBackPressed() {
saveDataFields();
return false;
}
}
The saveDataFields() is not too interesting. It just copies the data out of the UI views and saves them back to an object in the Activity.
after define event class and post event on Activity onBackPressed() i cant get event on fragment, some my activities opening above this fragment which that is child of MainActivity. i want to get some events that post from other opening activitis, but my code doesnt get this event on Fragment, but i can post event from Activity onBackPressed()
SignalActivityMarketDetailStateEvents class:
public class SignalActivityMarketDetailStateEvents {
private boolean activityMarketDetailState;
public SignalActivityMarketDetailStateEvents(boolean activityMarketDetailState) {
this.activityMarketDetailState = activityMarketDetailState;
}
public boolean isActivityMarketDetailState() {
return activityMarketDetailState;
}
}
ActivitySecond :
#Override
public void onBackPressed() {
EventBus.getDefault().post(new SignalActivityMarketDetailStateEvents(true));
}
Fragment to get event:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(SignalActivityMarketDetailStateEvents event) {
Log.e("EventBus ","Received");
}
#Override
public void onStart() {
EventBus.getDefault().register(this);
super.onStart();
}
#Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
#Override
public void onResume() {
EventBus.getDefault().register(this);
super.onResume();
}
in my Fragment this line doesnt work after post event:
Log.e("EventBus ","Received");
You are not mindful of the life cycle's of those activities. You could use the sticky events (postSticky) . Or update the state in some singleton and read that in onResume.
This is my first activity where Im making a post call. The bus provider is the default one in the otto sample app.
void openNextActivity()
{
manager.bus.post("Hi");
// Intent to my next Activity
}
This is my fragment in another activity where im subscribing for the data. The bus received is the same, however the subscribe method is not being called.
public class ProductListFragment extends BaseFragment {
String LOG_TAG = ProductListFragment.class.getCanonicalName();
public static ProductListFragment newInstance() {
ProductListFragment fragment = new ProductListFragment();
return fragment;
}
public ProductListFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().invalidateOptionsMenu();
}
#Override
public void onResume() {
super.onResume();
BusProvider.getInstance().register(this);
}
#Override
public void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}
#Subscribe public void onPostRecived(String s) {
Log.d(LOG_TAG, s);
}
}
There are no errors on anything being received, however if I put a button onclick on the fragment and post some content from there, the subscribe method is being called. For eg.
#OnClick(R.id.makePostCall) void call() {
BusProvider.getInstance().post("Hi");
}
I'm getting the appropriate log on this call. Any idea where the code is going wrong?
it seems you subscribe your second activity's fragment after sending stuff to event bus. Consider changing your logic
u send msg before intent;the BusProvider id registered after intent;
just try:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
BusProvider.getInstance().post("Hi");
}
},3000);
I have been researching this for a few days and have yet to find a working solution. There is lots of information available but because of my inexperience with Android I can't get any of the suggestions to work.
I have an Activity with a stack of 3 Fragments on top of it all of which are presented using FragmentManager Transactions and added to the backstack. While the third Fragment is active, I need to intercept the onBackPressed() method and perform some extra stuff before the Fragment is destroyed.
I have tried using Callbacks and Interfaces to capture onBackPressed() at the Activity and send it to the 3rd Fragment with no luck.
What is the proper way to have a Fragment deep in the stack watch for the Activity's onBackPressed() method.
Let me know if this is not clear.
Thanks for the help.
Not compiled and tested, but this lays out the basic approach:
public interface BackButonListener {
boolean OnBackButtonPressed();
}
public interface BackButtonWatchable {
void addBackButtonListener(BackButtonListener listener);
void removeBackButtonListener(BackButtonListener listener);
}
public class MyActivity extends Activity implements BackButtonWatchable {
...
private static ArrayList<BackButtonListener> backButtonListeners
= new ArrayList<BackButtonListener>();
#Override
public void addBackButtonListener(BackButtonListener listener) {
backButtonListeners.add(listener);
}
#Override
public void removeBackButtonListener(BackButtonListener listener) {
backButtonListeners.remove(listener);
}
...
#Override
public void onBackButtonPressed()
{
boolean supressBackButton = false;
for (BackButtonListener listener: backButtonListeners)
{
if (!listener.OnBackButtonPressed()) {
suppressBackButton = true;
}
}
if (!suppressBackButton) {
super.onBackButtonPressed();
}
}
}
public class MyFragment extends Fragment implements BackButtonListerer {
#Override
public void onResume()
{
((BackButtonWatchable)getActivity()).addBackButtonListener(this);
}
#Override
public void onPause() {
((BackButtonWatchable)getActivity()).removeBackButtonListener(this);
}
}
Crete interface
public interface OnBackPressedListener {
void onBackPressed();
}
and create field in activity
private OnBackPressedListener mListener;
and your onBackPressed() should look like
if (mListener != null) {
mListener.onBackPressed();
} else { /* do your acitivty usual stuff */ }
When fragment is created you register this fragment as mListener in your activity and don't forger to set it to null in onDestroy.
This is the post that answered my question. For a Android newbie, this told me where everything needed to go.
https://stackoverflow.com/a/30865486/2640458
The Fragment that needed to see the onBackPress() method from it's activity:
public class RatingFragment extends Fragment implements ContentActivity.OnBackPressedListener {
#Override
public void doBack() {
getFragmentManager().popBackStack();
}
The very important subscription to the listener in the above Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_rating, container, false);
((ContentActivity)getActivity()).setOnBackPressedListener(this);
}
The Activity that needs to send the onBackPress() method to the above Fragment:
public class ContentActivity extends Activity {
protected OnBackPressedListener onBackPressedListener;
public interface OnBackPressedListener {
void doBack();
}
public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
this.onBackPressedListener = onBackPressedListener;
}
#Override
public void onBackPressed() {
if (onBackPressedListener != null)
onBackPressedListener.doBack();
else
super.onBackPressed();
}
#Override
protected void onDestroy() {
onBackPressedListener = null;
super.onDestroy();
}
}