Android导航体系结构组件:如何将捆绑数据传递到startDestination

时间:2018-12-24 12:45:53

标签: java android android-architecture-components android-navigation android-architecture-navigation

我有一个活动,其中有一个NavHostFragment。活动收到其意图的某些值。我想将此数据传递到导航图的第一个片段,即startDestination。我找不到与此有关的任何文档。

我已经经历过this question on SO,但似乎找不到addDefaultArguments的{​​{1}}方法。

是否可以将捆绑软件传递给navController.getGraph()

8 个答案:

答案 0 :(得分:2)

在更新的导航文档中找到正确的方法后,回答我自己的问题。

在撰写此答案时,我正在使用Navigation 2.2.0-alpha01

如果要直接将某些数据作为主机活动的参数传递到起始目标,则需要在主机活动的onCreate()方法中手动设置主机的导航图,如下所示:

让您获得navController:

val navController by lazy { findNavController(R.id.<your_nav_host_id>) }

然后在主持人活动的onCreate()

val bundle = Bundle()
bundle.putString("some_argument", "some_value")
navController.setGraph(R.navigation.<you_nav_graph_xml>, bundle)

或者,如果您想将整个意图额外信息直接传递给startDestination:

navController.setGraph(R.navigation.<you_nav_graph_xml>, intent.extras)

由于intent.extras仅返回Bundle

  

使用setGraph()方法设置navGraph时,应避免在以下位置设置app:NavGraph属性   NavHostFragment定义,因为这样做会导致膨胀   并设置两次导航图。

在startDestination片段中读取这些参数时,

如果您使用Safe Args Plugin(强烈建议使用),则在您的片段中:

private val args by navArgs<DummyFragmentArgs>()

Safe Args插件会通过将Args附加到您的片段名称来生成Args类。例如,如果您将片段称为DummyFragment,那么安全Args会生成一个名为DummyFragmentArgs

的类

其中navArgs<>Android KTX中定义的扩展功能

如果您未使用Android KTX,则可以获取args对象,例如:

val args = DummyFragmentArgs.fromBundle(arguments!!)

一旦获取了arguments对象,就可以简单地获取参数:

args.someArgument

请注意我们如何传递"some_argument"作为参数,并使用安全参数将其读为someArgument

如果您不使用安全Args(虽然没有理由不使用它),则可以这样访问参数:

arguments?.getString("some_argument")

所有这些都记录在此处的“迁移到导航组件”文档中: https://developer.android.com/guide/navigation/navigation-migrate#pass_activity_destination_args_to_a_start_destination_fragment

答案 1 :(得分:1)

我也遇到了同样的问题,

这是我的解决方法:

    your_activity.xml
  1. 删除 NavHostFragment的xml设置:即删除 app:navGraph =“ @ navigation / nav_graph

这是XML的外观。

        <fragment
        android:id="@+id/nav_host"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        />
    在活动onCreate()中以编程方式
  1. 添加 NavHostFragment的设置。 然后使用NavGraph.addDefaultArguments(bundleData) api

    传递捆绑数据
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.editor_layout)
            setupNavigation()
        }
    
        private fun setupNavigation() {
            val navHostFragment = nav_host as NavHostFragment
            val navController = navHostFragment.navController
            val navInflater = navController.navInflater
            val graph = navInflater.inflate(R.navigation.nav_graph)
            graph.addDefaultArguments(intent!!.extras!!) // This is where you pass the bundle data from Activity to StartDestination 
            navHostFragment.navController.graph = graph
        }
    

更新:

Project Gradle文件中的依赖项:

dependencies {

    def nav_version = "1.0.0-alpha08"

    implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
    implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin}
}

注意::在导航组件版本1.0.0-alpha09中,由于某种原因,谷歌没有方法,因为addDefaultArguments()可能即将修复。但是较低版本的具有addDefaultArguments()方法。我已经在java和kotlin中进行了检查,因此请尝试使用1.0.0-alpha071.0.0-alpha08

答案 2 :(得分:0)

我也找不到这种方法。它在体系结构组件文档中不存在。

但这是将参数设置为起始目标的另一种方法:

// Kotlin Code, in Fragment
with(findNavController().graph) {
    get(startDestination).addArgument(...)
}

答案 3 :(得分:0)

我检查了源代码,发现在导航目标和参数方面有很多更改。 我认为传递参数以启动目标的正确方法是使用“ addArgument”方法,如下所示:

val argument1 = 1 //First value
val argument2 = "Value" //Second value
val navArgument1=NavArgument.Builder().setDefaultValue(argument1).build()
val navArgument2=NavArgument.Builder().setDefaultValue(argument2).build()
navController.getGraph().addArgument("Key1",navArgument1)
navController.getGraph().addArgument("Key2",navArgument2)

也许有更好的方法,但是我没有找到一个方法。

答案 4 :(得分:0)

class MainActivity : BaseActivity()  {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val navHostFragment = container as NavHostFragment
        val inflater = navHostFragment.navController.navInflater
        val graph = inflater.inflate(R.navigation.main_nav)

        var data : Data  = intent.getParcelableExtra("DATA") as Data
        var bundle : Bundle = Bundle()
        bundle.putParcelable("DATA", data)
        graph.addDefaultArguments(bundle)
        graph.addDefaultArguments(intent!!.extras!!)
        navHostFragment.navController.graph = graph

    }
}

在“活动”中添加以上代码,以使用导航发送数据

override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        var data = NavHostFragment.findNavController(this).graph.defaultArguments.getParcelable("DATA") as Booking

}

在片段端添加以上代码

答案 5 :(得分:0)

您可以像这样在图形中添加参数

<fragment
  android:id="@+id/exampleFragment"
  android:label="example_fragment"
  android:name="com.example.yourapp.ui.ExampleFragment"
  tools:layout="@layout/example_fragment">
<argument
  android:name="exampleArgs"
  app:argType="reference"
  android:defaultValue="@string/example"/>
</fragment>

https://developer.android.com/guide/navigation/navigation-pass-data

答案 6 :(得分:0)

导航1.0.0

        val navHostFragment = root_nav_host_fragment as NavHostFragment
        val navController = navHostFragment.navController
        val navInflater = navController.navInflater
        val graph = navInflater.inflate(R.navigation.navigation)
        val sectionId = intent.getIntExtra(KEY_SECTION_ID, -1)
        val bundle = bundleOf(KEY_SECTION_ID to sectionId)
        navHostFragment.navController.setGraph(graph, bundle)

答案 7 :(得分:0)

经过一些研究,我找到了解决方案。它与最新的导航库版本一起使用。请参考以下代码:

  1. 将此添加到您的活动布局中。注意:我们没有在xml文件中设置 app:navGraph 参数。我们将对其进行动态设置。

    <fragment
        android:id="@+id/fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        app:defaultNavHost="true" />
    
  2. 在您的活动Java文件中,编写以下代码,并进行相应的更改。使用 NavArgument 传递参数值,并将参数添加到自定义Navgraph中,然后设置图形。

    public class YourActivity extends AppCompatActivity {
         private NavArgument nameArg, mailArg;
    
         @Override
         protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.profile);
            nameArg = new NavArgument.Builder().setDefaultValue("your name").build();
            mailArg = new NavArgument.Builder().setDefaultValue("your email id").build();
            NavController navController = Navigation.findNavController(this, R.id.fragment);
            NavInflater navInflater = navController.getNavInflater();
            NavGraph navGraph = navInflater.inflate(R.navigation.nav_profile_graph);
            navGraph.addArgument("your name key", nameArg);
            navGraph.addArgument("your mail key", mailArg);
            navController.setGraph(navGraph);
        }
    }
    
  3. 编写下面的导航图,并将相同的参数键添加到起始片段。

    <?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/profile_basic">
    
       <fragment
          android:id="@+id/profile_basic"
          android:name="com.yourpackage.ProfileBasicFragment"
          android:label="Profile Basic"
          tools:layout="@layout/fragment_profile_basic">
    
          <argument android:name="your name key"
              app:argType="string"/>
    
          <argument android:name="your mail key"
              app:argType="string"/>
    
       </fragment>
    </navigation>
    
  4. 在您的片段中,只需使用getArguments()函数获取值即可。

    String name = getArguments().getString("your name key");
    String mail = getArguments().getString("your mail key");