简体   繁体   中英

Android Navigation Component - Why add arguments in the navigation graph?

I've been following CodingWithMitch's tutorial (and github code ) to Navigation Component, but used Java instead of Kotlin. That hasn't brought any issues however.

My question is, without using Safe Args, what is the point to adding arguments in the nav_graph.xml .

In this example, SpecifyAmountFragment requires a String argument from the previous Fragment, called ChooseRecipientFragment :

Design View of nav_graph.xml : 设计视图连接ChooseRecipientFragment---->指定AmmountFragment---->confirmationFragment

Code snippet from the nav_graph.xml :

<fragment
        android:id="@+id/specifyAmountFragment"
        android:name="com.asfartz.navigation_component_basics.SpecifyAmountFragment"
        android:label="fragment_specify_amount"
        tools:layout="@layout/fragment_specify_amount">

        <argument android:name="recipient"
            app:argType="string" />

        <action
            android:id="@+id/action_specifyAmountFragment_to_confirmationFragment"
            app:destination="@id/confirmationFragment"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right"
            app:popUpTo="@id/mainFragment"
            app:popUpToInclusive="false" />
    </fragment>

Java code:

public class SpecifyAmountFragment extends Fragment {

    private NavController navController;
    private Button bSend, bCancel;
    private String recipient;
    private TextView tvRecipient;
    private TextInputEditText inputAmount;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_specify_amount, container, false);
        bSend = view.findViewById(R.id.send_btn);
        bCancel = view.findViewById(R.id.cancel_btn);
        tvRecipient = view.findViewById(R.id.recipient);
        inputAmount = view.findViewById(R.id.input_amount);

        recipient = getArguments().getString("recipient");

        String messagge = "Sending money to " + recipient;
        tvRecipient.setText(messagge);
        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        navController = Navigation.findNavController(view);

        bSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!TextUtils.isEmpty(inputAmount.getText())) {
                    Money money = new Money(new BigDecimal(inputAmount.getText().toString()));
                    Bundle b = new Bundle();
                    b.putString("recipient", recipient);
                    b.putParcelable("money", money);

                    navController.navigate(R.id.action_specifyAmountFragment_to_confirmationFragment, b);
                } else {
                    Toast.makeText(getActivity(), "Enter an amount", Toast.LENGTH_SHORT).show();
                }
            }
        });

        bCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (getActivity() != null) {
                    getActivity().onBackPressed();
                } else {
                    Toast.makeText(getContext(), "Activity is null", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

I'm receiving the bundle in OnCreateView, from which I'm taking the required String argument that I've declared in the nav_graph.xml . And later on, I'm sending this data forward in another bundle (in the bSend.setOnClickListener(...) ).

If I comment out all the <argument> tags and run the app again, the app will still work as it should (receiving the data from one fragment and passing it to another). There is no validation, so why add these tags at all, besides for clarity maybe?

When using Navigation architecture component, you are not suppose to use recipient = getArguments().getString("recipient"); Instead, you should use generated class of the destination which should be SpecifyAmountFragmentArgs and get your data this way: SpecifyAmountFragment.fromBundle(Pass arguments here).getRecipient which will provide type safety.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM