Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Up vs Back #6

Open
vpratfr opened this issue Jul 31, 2015 · 5 comments
Open

Up vs Back #6

vpratfr opened this issue Jul 31, 2015 · 5 comments

Comments

@vpratfr
Copy link

vpratfr commented Jul 31, 2015

Hi,

how do you handle "up" navigation with architect navigators?

@0xjohnnycagewins
Copy link

What we did in our project is to create a module in your main Activity that will provide the ActivityPresenter. It's injected in the Activity.
We then created an interface to handle options item selected, such as this for example:

public interface OptionsItemSelectedHandler {
    boolean onOptionsItemSelected(MenuItem item);
    // other toolbar stuff for example boolean onCreateOptionsMenu(Menu menu)
}

The Activity presenter implements this interface, so in the Activity you simply override the method and call the presenter:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    return mActivityPresenter.onOptionsItemSelected(item);
}

The presenter holds a reference to a OptionsItemSelectedHandler with a setter. Just like the Activity, it calls this method on the reference to a OptionsItemSelectedHandler, if any:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (mOptionsItemSelectedHandler != null) {
        return mOptionsItemSelectedHandler.onOptionsItemSelected(item);
    } else {
        return false;
    }
}

If for a view you are interested in handling the options selected events, the presenter has to implement the OptionsItemSelectedHandler interface. Then, by making the component of the view presenter dependant on the main Activity component, it ActivityPresenter gets injected in the view presenter. So in the public void onLoad(Bundle savedInstanceState) method, set itself as the mOptionsItemSelectedHandler so the presenter can handle the events. That's the way we do for every Activity methods we want to be handled by the view presenter, such as protected void onActivityResult(int requestCode, int resultCode, Intent data).

Normally we would set the OptionsItemSelectedHandler to null in the public void dropView(MainView view) method, but the view can be dropped and retaken (recreated) without public void onLoad(Bundle savedInstanceState) being called. It would be nice to override void takeView(V view) but it's final :( We thought about creating an interface with an public void onViewCreated() method and let all of our view presenters implement it and then call the method in the constructor of the view, so then we can set any listener in the presenter to null in the public void dropView(MainView view) method. Not sure it's the best way, if you have any suggestion I'll be glad to hear them.

That being said, if you only want to handle the "up" menu button, it's much easier. You simply have to call mNavigator.delegate().onBackPressed() in the main Activity public boolean onOptionsItemSelected(MenuItem item) method, as so:

boolean onOptionsItemSelected(MenuItem item);
    switch (item.getItemId()) {
        case android.R.id.home:
            mNavigator.delegate().onBackPressed();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

@vpratfr
Copy link
Author

vpratfr commented Aug 5, 2015

I know how to handle the button from the activity. Just wanted to know if the library provided any framework to provide a history corresponding to up navigation from a screen.

UP and BACK are two different navigation patterns, and most of the time, UP should not be treated the same as BACK (official documentation).

When working with activities, the pattern is to specify the parent task either via XML in the manifest or from code SDK docs:

<activity ... >
        <!-- Parent activity meta-data to support 4.0 and lower -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity" />
    </activity>

Then when navigating up, you have to rebuilt a back stack corresponding to the new application state after up navigation SDK docs:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    // Respond to the action bar's Up/Home button
    case android.R.id.home:
        Intent upIntent = NavUtils.getParentActivityIntent(this);
        if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
            // This activity is NOT part of this app's task, so create a new task
            // when navigating up, with a synthesized back stack.
            TaskStackBuilder.create(this)
                    // Add all of this activity's parents to the back stack
                    .addNextIntentWithParentStack(upIntent)
                    // Navigate up to the closest parent
                    .startActivities();
        } else {
            // This activity is part of this app's task, so simply
            // navigate up to the logical parent activity.
            NavUtils.navigateUpTo(this, upIntent);
        }
        return true;
    }
    return super.onOptionsItemSelected(item);
}

If we transpose all that to the mortar architect components, presenters are responsible for building the new back stack instead of activities.

Just like we have navigator.delegate().onBackPressed(), maybe it would be worth adding navigator.delegate().onUpPressed() and via clever interface implementation automatically have a presenter method called (like Presenter implements UpNavigationHandler and its onUpNavigation method gets called by the navigator).

PS : just like for activity result and all such common use cases, because mortar architect is all about killing boiler plate code, it would be nice to have these common use cases wired with just the presenter implementing some interfaces and a single line in the activity code.

@0xjohnnycagewins
Copy link

ah ok I get your point now. I agree it would be worth adding it!

@jjvargas
Copy link

jjvargas commented Oct 5, 2015

@cartierjf I know this is very descriptive but I still have not been able to make this work, Do you have a gist of the full classes where this is implemented? Cheers.

@0xjohnnycagewins
Copy link

@jjvargas this has been discussed in #15. As stated, it turns out that this is not needed since you can add the listeners directly on the toolbar. See this for reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants