简体   繁体   中英

Pass data from single activity to start destination fragment using Architecture Component Navigation

I've got the following Activity , which is the single one in my app:

MainActivity.java :

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        PermissionState state = PermissionState.get(this);
        if (state == PermissionState.GRANTED) {
            getWindow().setBackgroundDrawable(new ColorDrawable(-1));
        }

        super.onCreate(savedInstanceState);

        ActivityMainBinding mainActivityBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        setSupportActionBar(mainActivityBinding.toolbarMain);
        NavigationUI.setupWithNavController(mainActivityBinding.toolbarMain, Navigation.findNavController(this, R.id.nav_host_fragment));
    }
}

The layout associated with the Activity is the following and was created following this Android Developers tutorial.

activity_main.xml :

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:popupTheme="@style/AppTheme.PopupOverlay" />

        </com.google.android.material.appbar.AppBarLayout>

        <fragment
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph" />

    </LinearLayout>

</layout>

The navigation graph is the following:

nav_graph.xml :

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/mainFragment">

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.example.myapp.MainFragment"
        android:label="@string/app_name"
        tools:layout="@layout/fragment_main">
        <action
            android:id="@+id/action_mainFragment_to_settingsFragment"
            app:destination="@+id/settingsFragment" />
    </fragment>

    <fragment
        android:id="@+id/settingsFragment"
        android:name="com.example.myapp.SettingsFragment"
        android:label="@string/settings" />
</navigation>

Now, other than the hosting Activity , my app has two Fragment s, one is the main, the other is for settings.
The main Fragment is the start destination of my app, and there I would like to retrieve the MainActivity variable "PermissionState state" to perform some actions based on the state of the permissions, like hiding or showing some View s.

Using Android Architecture Component Navigation API version 1.0.0-beta01 onwards, what is the correct, nondeprecated strategy to pass data from the hosting Activity to the start destination Fragment , maybe using Safe Args if possible?

Find a solution,works fine but i don't like it there's must be a better solution for that.

In your Activity:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val navController = findNavController(R.id.nav_controller_fragment)
    val bundle = Bundle()
    bundle.putString("name","your value")
    navController.setGraph(navController.graph,bundle)
}

In your start Fragment:

  val args: MainFragmentArgs by navArgs()
  textView.text = args.name

In your navGraph:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/mobile_navigation"
        app:startDestination="@id/mainFragment">

<fragment android:id="@+id/mainFragment"
          android:name="com.haidar.mediasaver.fragments.MainFragment"
          android:label="main_fragment"
          tools:layout="@layout/main_fragment">
    <argument android:name="name"
              app:argType="string"/>
</fragment>

If you use safe args, you need to do:

  1. Remove the app:navGraph attribute from your NavHostFragment
  2. Then call:

     findNavController(R.id.nav_controller_fragment) .setGraph( R.navigation.nav_graph, MainFragmentArgs("your values").toBundle() ) 

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