简体   繁体   中英

Check if arguments exists when navigating to Fragment using SafeArgs

I migrated to Navigation Components and since I use Fragments now, I do no longer call onActivityResult() in my Fragment.

I defined the arguments that I pass to AddEditTaskFragment and want to send the modified arguments back to the TodayFragment. Since onViewCreated() is called every time I navigate to the TodayFragment, I want to check if I am actually passing arguments to it to save the Task in my DB then.

Since AddEditTaskFragmentArgs.fromBundle(getArguments()) != null does not work, what is the recommended way to check if a fragment is receiving arguments?

This is how I navigate back to the calling fragment.

AddEditTaskFragmentDirections.ActionAddEditTaskFragmentToHomeFragment action = AddEditTaskFragmentDirections.actionAddEditTaskFragmentToHomeFragment();

action.setTitle(title);
if (id != -1) action.setId(id);
action.setPriority(priority);
action.setAddanote(duedate);
action.setDuedate(remindme);
action.setRemindme(addanote);
action.setModeEdit(modeEdit);

Navigation.findNavController(getView()).navigate(action);

Now I want todo something like:

if (AddEditTaskFragmentArgs.fromBundle(getArguments()) != ...?) {
    // Receive data from action
    String title = AddEditTaskFragmentArgs.fromBundle(getArguments()).getTitle().trim();
    int priority = AddEditTaskFragmentArgs.fromBundle(getArguments()).getPriority();
    String duedate = AddEditTaskFragmentArgs.fromBundle(getArguments()).getDuedate();
    String remindme = AddEditTaskFragmentArgs.fromBundle(getArguments()).getRemindme();
    String addanote = AddEditTaskFragmentArgs.fromBundle(getArguments()).getAddanote().trim();
    boolean modeEdit = AddEditTaskFragmentArgs.fromBundle(getArguments()).getModeEdit();
    int id = AddEditTaskFragmentArgs.fromBundle(getArguments()).getId();

    Task task = new Task(title, addanote, priority, duedate, remindme);
    taskViewModel.insert(task);

    Toast.makeText(getContext(), "Task saved.", Toast.LENGTH_SHORT).show();
}

Don't know if you have figured out the answer since but here's how I'm generally doing.

In your XML navigation resource file, arguments need to be declared in each of your destination fragments (in your case, it seems to be both fragments as AddEditTaskFragmentArgs is supposed to receive some arguments, modify them and send them back to the TodayFragment ). I assume you have something like this:

<?xml version="1.0" encoding="utf-8"?>
<navigation>

    <!-- ... -->

    <fragment
        android:id="@+id/actionAddEditTaskFragmentToHomeFragment"
        android:name="...AddEditTaskFragment"
        android:label="..."
        tools:layout="..." >
        <argument
            android:name="id"
            app:argType="integer"
            android:defaultValue="3" />
        <argument
            android:name="title"
            app:argType="string" 
            app:nullable="true" />

            <!-- Other  arguments -->

    </fragment>

    <!-- Other fragments -->

</navigation>

In the source fragment, you can set arguments by using setters (as you did) or pass them directly in the action constructor (it depends of argument types as well as if you specified a default value for them). More information can be found in the official documentation .

Since I notice that you did not supply any argument to your constructor, my guess is that you have provided default values for all your arguments.

Then, in your destination fragment AddEditTaskFragment , you can do:

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    // Get arguments from bundle, if any
    if (getArguments() != null) {
        AddEditTaskFragmentArgs args = AddEditTaskFragmentArgs.fromBundle(getArguments()); 

        if (args.getTitle() != null) {
            String title = args.getTitle();
        } else {
            // Title is null because it's a String, that we allowed nullable and because user did not set it
        }

        int id = args.getId(); // An int cannot be null and we specified a default value

        // Check other arguments ...
    }
    else {
        // No argument was provided
        // Use default values or throw an error
    }
}

If you absolutely want to be sure to receive arguments, you can use requireArguments() instead. This will throw an error at runtime if the Bundle object passed to the fragment is null . However, this does not prevent that all your arguments won't be null (see the android documentation link above) so you have to perform the checks that really matter for you, just like before:

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    AddEditTaskFragmentArgs args = AddEditTaskFragmentArgs.fromBundle(requireArguments()); 

    if (args.getTitle() != null) {
        String title = args.getTitle();
    } else {
        // Title is null because it's a String, that we allowed nullable and because user did not set it
    }

    int id = args.getId(); // An int cannot be null and we specified a default value

    // Check other arguments ...
}

Hope that helps :)

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