Search code examples
androidandroid-fragmentsonactivityresultotto

Android. Otto Bus doesn't fire event from onActivityResult() method of Fragment to Activity


I have BaseActivity with register() and unregister() methods:

public class BaseActivity extends AppCompatActivity{

    ...

    @Override
    protected void onResume() {
        super.onResume();
        // Register ourselves so that we can provide the initial value.
        BusProvider.getInstance().register(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Always unregister when an object no longer should be on the bus.
        BusProvider.getInstance().unregister(this);
    }

    protected void setFragment(Fragment fragment){
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(ROOT_CONTAINER_ID, fragment);
        if(!isFinishing()) {
            transaction.commitAllowingStateLoss();
        }
    }


}

I have ChildActivity which fire DoneEvent to FrDetails fragment and it works fine.

public class ChildActivity extends BaseActivity implements View.OnClickListener{

    private ImageView btnDone;

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

        btnDone = (ImageView) toolbarView.findViewById(R.id.btnDone);
        btnDone.setOnClickListener(this);

        setFragment(FrDetails.newInstance());
    }    

    @Override
    public void onClick(View v) {
        int viewId = v.getId();

        switch (viewId){
            case R.id.btnDone:

                BusProvider.getInstance().post(new DoneEvent());

                break;
            default:
                break;
        }
    }

    @Subscribe
    public void onDataFilled(DataFilledEvent event) {
        Log.e("Data filled", "Yessss");
    }
}

But DataFilledEvent doesn't fire to ChildActivity from onActivityResult method of FrDetails fragment. I've called register() and unregister() methods in FrBase fragment. FrDetails fragment is child for FrBase fragment.

public abstract class FrBase extends Fragment {
    ...

    @Override
    public void onResume() {
        super.onResume();
        BusProvider.getInstance().register(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        BusProvider.getInstance().unregister(this);
    }

}

This is my FrDetails class:

import com.squareup.otto.Subscribe;

public class FrDetails extends FrBase implements View.OnClickListener{

...

   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View baseView = inflater.inflate(R.layout.one_fragment, null);
        button = (Button) baseView.findViewById(R.id.btn1);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //WORK FINE HERE!
                BusProvider.getInstance().post(new DataFilledEvent());
            }
        });

        button2 = (Button) baseView.findViewById(R.id.btn2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getBaseActivity(), ThirdActivity.class);
                startActivityForResult(intent, SELECT_YEAR);
            }
        });
    }

    @Subscribe
    public void onDone(DoneEvent event) {
        //WORKS FINE HERE!
        Toast.makeText(getActivity(), "Done", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        //Log is called correctly
        Log.e("OK", "log");

        //DOENS'T WORK HERE!
        BusProvider.getInstance().post(new DataFilledEvent());

    }
}

Why BusProvider.getInstance().post(new DataFilledEvent()); doesn't fire event from onActivityResult() to ChildActivity? But it works if we fire event by click on button in FrDetails fragment.

Thanks in advance.


Solution

  • Based on the documentation on onActivityResult() (relevant snippet only):

    You will receive this call immediately before onResume() when your activity is re-starting.

    In other words, the event is fired before your activity has registered itself with the bus, because registration happens in onResume().

    If you want to be able to fire and receive events at an earlier stage in the activity's life cycle, you should change registration (and unregistration) accordingly.

    Alternatively, you may be able to get away with simply registering in onActivityResult() also. I haven't looked at Otto's code for a while, but I imagine that registering an already registered event handler will not result in the handler receiving events more than once. Do note that in this case you'll have to take into account the fact that your activity may not be in a state you expect it to be. That is, it will be somewhere inbetween onActivityResult() and onResume().