繁体   English   中英

Android 导航架构组件:如何将捆绑数据传递给 startDestination

[英]Android Navigation Architecture Component: How to pass bundle data to startDestination

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

我已经在 SO 上解决这个问题,但我似乎找不到navController.getGraph()addDefaultArguments方法。

是否可以将 bundle 传递给startDestination

我也遇到过同样的问题,

这就是我如何解决它:

  1. 除去 NavHostFragment的在xml设置your_activity.xml :即移除应用:navGraph =“@导航/ 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"
        />
  1. onCreate()活动中以编程方式添加 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

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

  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传递您的参数值并将参数添加到您的自定义导航图,然后设置图。

     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");

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

<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

虽然这是一个迟到的答案,但有一种非常简单的方法可以使用导航控制器/导航架构传递包:

将发送数据的片段

//Best to put in onViewCreated
val navController = findNavController()

//Put in code where you want to start navigation
val b = Bundle()
b.putString("key_1", "Data 1")
b.putString("key_2", "Data 2")

navController.navigate(R.id.action_signupFragment_to_signinFragment,b)

将接收数据的片段

val data_1: String = arguments?.getString("key_1")?:""
val data_1: String = arguments?.getString("key_2")?:"" 

根据您发送的数据类型,您需要更新安全调用或使变量可以为空。

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

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

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

我检查了源代码,看到有关导航目标和参数的很多变化。 我认为将参数传递给起始目的地的正确方法是使用'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)

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

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

    }
}

在Activity中添加上述代码,使用导航发送数据

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

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

}

在片段方面添加上面的代码

导航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)

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

在撰写此答案时,我使用的是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时,应避免在NavHostFragment定义中设置app:NavGraph属性,因为这样做会导致两次导航图膨胀和设置。

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

如果您使用的是Safe Args插件 (非常推荐),那么在您的片段中:

private val args by navArgs<DummyFragmentArgs>()

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

其中navArgs<>Android KTX中定义的扩展函数

如果您没有使用Android KTX,您可以获取args对象,如:

val args = DummyFragmentArgs.fromBundle(arguments!!)

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

args.someArgument

注意我们如何将"some_argument"作为参数传递,我们使用Safe Args将其作为someArgument读取

如果您没有使用Safe Args(没有理由不使用它),您可以像这样访问您的参数:

arguments?.getString("some_argument")

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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