Skip to content

Navigation

Artur edited this page Sep 3, 2017 · 1 revision

Presenters have a method getNavigation(), which returns a Navigation class object or null. null is returned in case if the presenter has currently no active View.

Navigation class contains 4 methods, using a ComplexNavigationUnit class object as an argument to perform standard activities or navigating between screens:

  • public void open(ComplexNavigationUnit navigationUnit) to open a new screen
  • public <T> T getData(ComplexNavigationUnit<T, ?> navigationUnit) to obtain the data transferred to it via the previous method on the opened screen
  • public <R> void setResult(ComplexNavigationUnit<?, R> navigationUnit) to save screen operation results
  • public <R> R getResult(ComplexNavigationUnit<?, R> navigationUnit, int requestCode, int resultCode, Intent data) to obtain the data saved using the previous method

ComplexNavigationUnit class and its simplified child class NavigationUnit contain the corresponding empty methods navigate, getNavigationData, setNavigationResult, and getNavigationResult, whose implementation you have to write.

Such an approach serves to encapsulate all the code we write inside Activity to open it and transfer there some data within the ComplexNavigationUnit inheritance classes. Additionally, this approach enables you to write less code if Activity and Fragment in it use the same data.

Standard approach example:

public class LoginActivity extends AppCompatActivity {
    private static final String EXTRA_LOGIN_TEXT = "EXTRA_LOGIN_TEXT";

    // constructing intent with data
    public static Intent getNavigationIntent(String login, Context context) {
        return new Intent(context, LoginActivity.class)
                .putExtra(EXTRA_LOGIN_TEXT, login);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        // obtaining data and transferring further to LoginFragment
        String loginText = getIntent().getStringExtra(EXTRA_LOGIN_TEXT);
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.content, LoginFragment.create(loginText))
                .commit();
    }
}

public class LoginFragment extends Fragment {

    // constructing LoginFragment with data
    public static LoginFragment create(String loginText) {
        LoginFragment fragment = new LoginFragment();
        Bundle arg = new Bundle();
        arg.putString(ARG_LOGIN, loginText);
        fragment.setArguments(arg);
        return fragment;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // getting data from Bundle args
        loginField.setText(getArguments().getString(ARG_LOGIN));
    }
}

Reamp way:

public class LoginNavigationUnit extends NavigationUnit<String> {

    private static final String EXTRA_LOGIN_TEXT = "EXTRA_LOGIN_TEXT";
    private String loginText;

    public LoginNavigationUnit withLoginText(String loginText) {
        this.loginText = loginText;
        return this;
    }

    @Override
    protected void navigate(Navigation navigation) {
        Intent loginIntent = new Intent(navigation.getActivity(), LoginActivity.class);
        loginIntent.putExtra(EXTRA_LOGIN_TEXT, this.loginText);
        navigation.getActivity().startActivity(loginIntent);
    }

    @Override
    protected String getNavigationData(Navigation navigation) {
        return navigation.getActivity().getIntent().getStringExtra(EXTRA_LOGIN_TEXT);
    }
}

public class LoginFragmentPresenter extends BasePresenter<LoginFragmentStateModel> {
    @Override
    public void onFirstCreate() {
        super.onFirstCreate();
        // receiving data in the fragment straight away
        String loginText = getNavigation().getData(new LoginNavigationUnit());
    }
}

// Use
getNavigation().open(new LoginNavigationUnit().withLoginText("My Login"))

All data packing and unpacking operations as well as opening the screen itself are now isolated in one place separately from the screens. This provides the following functions:

  • Change the navigation behavior without affecting the Activity / Fragment screen code
  • Pick data packing and unpacking method, remaining within one class
  • If necessary, different NavigationUnits can be added for navigation behavior flexible configuration without affecting NavigationUnits which are already written.
Clone this wiki locally