简体   繁体   中英

Android Navigation Component Activity Intent Flags

I have created a navigation action from a fragment to an activity, but I have no way of clearing the back stack. When I execute the navigation action from my fragment to my new activity, and I press the back button, I am taken back to the previous activity and previous fragment. I have no way of setting Intent flags, using the navigation graph, to clear the previous activity from the back stack.

<fragment
    android:id="@+id/loginFragment"
    android:name="com.myapp.auth.LoginFragment"
    android:label="login_fragment"
    tools:layout="@layout/login_fragment" >
    <action
        android:id="@+id/action_loginFragment_to_webActivity"
        app:destination="@id/webActivity"
        app:popUpTo="@id/loginFragment"
        app:popUpToInclusive="true" />
</fragment>
<activity
    android:id="@+id/webActivity"
    android:name="com.myapp.web.WebActivity"
    android:label="activity_web"
    tools:layout="@layout/activity_web" >
</activity>

PopTo and Inclusive flags have no effect on the back button when navigating from a fragment to a new activity, even though they can be set in the graph editor. I am able to navigate, using the back button, to the previous activity that I no longer want in the stack.

Before migrating to the navigation graph, I could just specify this behavior with Intent flags:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

How can I achieve the same thing with the navigation graph?

I had to hack my way through the same problem. To solve this, the first thing you have to do is to create an action to navigate to the Activity, as you already had done.

For example:

<action
    android:id="@+id/action_frag_to_myActivity"
    app:destination="@id/myActivity"
    app:popUpTo="@id/myActivity" />

Now, you can pass arguments to the Activity as intent extras, so you can take advantage of that to make the destination Activity do the "dirty work" and clear the back stack for you.

Say that you have this Activity tag inside your navigation graph:

<activity
    android:id="@+id/myActivity"
    android:name="com.dummy.MyActivity"
    android:label="activity_my" />

You could add an argument in it and add a default value. For example:

 <activity
    android:id="@+id/myActivity"
    android:name="com.dummy.MyActivity"
    android:label="activity_my">

        <argument
            android:name="clearBackstack"
            app:argType="boolean"
            android:defaultValue="true" />

</activity>

Then once you call findNavController().navigate(R.id.myActivity) it'll pass an intent extra with the key "clearBackstack" which you can read inside the Activity onCreate() method. Something like the example below.

MyActivity.kt

private val EXTRA_LOGOUT = "clearBackstack"

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    if (intent.extras?.getBoolean(EXTRA_LOGOUT) == true) {
        clearBackstack()
    } else {
        setContentView(R.layout.activity_my)
    }
}

private fun clearBackstack() {
    startActivity(Intent(this, MyActivity::class.java).apply {
        addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
    })

    finish()
}

Keep in mind you can tinker around with the arguments and customize what you want to do on the destination Activity. You could also modify the value once you navigate to it. You can read more about it here in the docs .

Referencing Fatih's answer

val extras = ActivityNavigator.Extras.Builder()
        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
        .addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        .build()
findNavController().navigate(BlaBlaActivityDirections.actionFooBarToBlaBlaActivity(), extras)

Note You need to add these flags to the activity stack:

  1. FLAG_ACTIVITY_CLEAR_TASK : sets the activity as the root task. used with
  2. FLAG_ACTIVITY_NEW_TASK : treats the activity as launcher activity.
  3. FLAG_ACTIVITY_REORDER_TO_FRONT : brings the activity to front. Use this only if you have other activities on the stack and you don't want to clear it.

You can control properties like singleTop from the action element, in the navigation definition.

The properties are available in the navigation editor as well.

在此处输入图片说明

You can add an intent flag to navigator extras.

val extras = ActivityNavigator.Extras.Builder()
   // Add your flags 
   .addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
   .build()

// Navigate with extras 
findNavController().navigate(destination, extras)

You can check how the intent flags are handled in ActivityNavigator.navigate() from the source code

Alternatively, you can use navigation options if the only flag you will set is FLAG_ACTIVITY_SINGLE_TOP .

val navOptions = NavOptions.Builder().setLaunchSingleTop(true).build()
findNavController().navigate(destination, navOptions)

You can check how nav options are checked in ActivityNavigator.navigate() from the source code

If you are moving from one activity to another.

That's how I solved the same question. I hope it helps.

firstIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

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