使用带有参数的片段进行导航

问题描述

我的应用程序由一个ViewPager组成,其中包含相同类型的9 Fragments。如下所示,此片段在其构造函数中采用一个参数。

NewsFragment.kt

class NewsFragment(section: NewsSection) : Fragment() {
   //...
}

CategoryFragmentPagerAdapter.kt

class CategoryFragmentPagerAdapter(fm: FragmentManager)
    : FragmentPagerAdapter(fm,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {

    override fun getItem(position: Int): Fragment =
        NewsFragment(NewsSection.getItem(position))

    override fun getCount(): Int = NewsSection.values().size

    override fun getPageTitle(position: Int): CharSequence =
         NewsSection.getItem(position).sectionName

}

此片段包含一些应将用户导航到其他片段的操作。

我尝试使用Jetpack Navigation Component方法来实现导航,但是由于导航图无法接受带有参数的片段,因此看起来它会出错。

在这种情况下如何实施Navigation的任何想法?

编辑


这是我在活动FragmentContainerView中的XML layout

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

这就是我在活动中实现navController的方式

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        setupDataBinding()
        val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
        val navController = navHostFragment.navController
}

我没有添加任何其他配置,这是运行应用程序时弹出的error

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.domain.news/com.domain.news.ui.activities.MainActivity}: android.view.InflateException: Binary XML file line #18 in com.domain.news:layout/activity_main: Binary XML file line #22 in com.domain.news:layout/content_main: Error inflating class androidx.fragment.app.FragmentContainerView
        at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:3307)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3446)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:224)
        at android.app.ActivityThread.main(ActivityThread.java:7548)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
     Caused by: android.view.InflateException: Binary XML file line #18 in com.domain.news:layout/activity_main: Binary XML file line #22 in com.domain.news:layout/content_main: Error inflating class androidx.fragment.app.FragmentContainerView
     Caused by: android.view.InflateException: Binary XML file line #22 in com.domain.news:layout/content_main: Error inflating class androidx.fragment.app.FragmentContainerView
     Caused by: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment com.domain.news.ui.fragments.news.NewsFragment: Could not find Fragment constructor
        at androidx.fragment.app.Fragment.instantiate(Fragment.java:563)
        at androidx.fragment.app.FragmentContainer.instantiate(FragmentContainer.java:57)
        at androidx.fragment.app.FragmentManager$3.instantiate(FragmentManager.java:390)
        at androidx.navigation.fragment.FragmentNavigator.instantiateFragment(FragmentNavigator.java:132)
        at androidx.navigation.fragment.FragmentNavigator.navigate(FragmentNavigator.java:162)
        at androidx.navigation.fragment.FragmentNavigator.navigate(FragmentNavigator.java:58)
        at androidx.navigation.NavGraphNavigator.navigate(NavGraphNavigator.java:71)
        at androidx.navigation.NavGraphNavigator.navigate(NavGraphNavigator.java:28)
        at androidx.navigation.NavController.navigate(NavController.java:1049)
        at androidx.navigation.NavController.onGraphCreated(NavController.java:633)
        at androidx.navigation.NavController.setGraph(NavController.java:586)
        at androidx.navigation.NavController.setGraph(NavController.java:551)
        at androidx.navigation.NavController.setGraph(NavController.java:533)
        at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.java:238)
        at androidx.fragment.app.Fragment.performCreate(Fragment.java:2684)
        at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:280)
        at androidx.fragment.app.FragmentManager.movetoState(FragmentManager.java:1175)
        at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
        at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1818)
        at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:303)
        at androidx.fragment.app.FragmentContainerView.<init>(FragmentContainerView.java:166)
        at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:51)
2020-09-19 20:39:22.012 16179-16179/com.domain.news E/AndroidRuntime:     at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
        at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:356)
        at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:335)
        at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1073)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1001)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:965)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:1127)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:1130)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
        at android.view.LayoutInflater.parseInclude(LayoutInflater.java:1267)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:1123)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
        at android.view.LayoutInflater.parseInclude(LayoutInflater.java:1267)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:1123)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:686)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:538)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:481)
        at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:696)
        at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:170)
        at androidx.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:303)
        at androidx.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:284)
        at com.domain.news.utils.delegates.ActivityBindingProperty.createActivityBinding(Databinding.kt:20)
        at com.domain.news.utils.delegates.ActivityBindingProperty.getValue(Databinding.kt:16)
        at com.domain.news.ui.activities.MainActivity.getBinding(UnkNown Source:10)
        at com.domain.news.ui.activities.MainActivity.setupBinding(MainActivity.kt:42)
        at com.domain.news.ui.activities.MainActivity.onCreate(MainActivity.kt:34)
        at android.app.Activity.performCreate(Activity.java:7893)
        at android.app.Activity.performCreate(Activity.java:7880)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
        at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:3282)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3446)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:224)
        at android.app.ActivityThread.main(ActivityThread.java:7548)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
     Caused by: java.lang.NoSuchMethodException: com.domain.news.ui.fragments.news.NewsFragment.<init> []
        at java.lang.class.getConstructor0(Class.java:2332)
        at java.lang.class.getConstructor(Class.java:1728)
        at androidx.fragment.app.Fragment.instantiate(Fragment.java:548)
            ... 66 more

最后三行显示原因是片段构造器

解决方法

首先,打开您的

app:navGraph="@navigation/navigation

错误明确指出,该错误无法使您的XMl膨胀((可能是@ navigation / navigation XML文件的第18行中的某处)

,

您需要在片段的参数束中而不是在构造函数中传递数据。 为此,NewsSection需要实现Parcelable

在导航xml中,您可以执行以下操作:

<fragment
        android:id="@+id/newsFragment"
        android:name="com.example.NewsFragment"
        android:label="ProductListerFragment"
        tools:layout="@layout/fragment_news_secion">
        <argument
            android:name="newsSection"
            app:argType="com.example.NewsSection" />

在片段中,您要从以下位置导航:

val newsSection = NewsSection(....)
val bundle = bundleOf("newsSection" to newsSection)
view.findNavController().navigate(R.id.newsAction,bundle)

NewsFragment中:

val newsSection = arguments?.getParcelable("newsSection") as? NewsSection

有关更多详细信息,请参见https://developer.android.com/guide/navigation/navigation-pass-data