使用 JetPack Navigation 启动带有 recyclerview 的片段

Starting a fragment with a recyclerview using JetPack Navigation

我有一个应用 MainActivity 但所有工作都在片段中。 我使用 JetPack 导航将片段布局设为 HomePage。它奏效了。但是当我添加回收器视图时它崩溃了。

错误是这样的:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.saheralsous.android, PID: 12418
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.saheralsous.android/com.saheralsous.android.MainActivity}: android.view.InflateException: Binary XML file line #20 in com.saheralsous.android:layout/activity_main: Binary XML file line #20 in com.saheralsous.android:layout/activity_main: Error inflating class fragment
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        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:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: android.view.InflateException: Binary XML file line #20 in com.saheralsous.android:layout/activity_main: Binary XML file line #20 in com.saheralsous.android:layout/activity_main: Error inflating class fragment
     Caused by: android.view.InflateException: Binary XML file line #20 in com.saheralsous.android:layout/activity_main: Error inflating class fragment
     Caused by: java.lang.NullPointerException: null cannot be cast to non-null type androidx.recyclerview.widget.RecyclerView
        at com.saheralsous.android.PhotoGalleryFragment.onCreateView(PhotoGalleryFragment.kt:45)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:518)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
        at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
        at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3065)
        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
        at androidx.fragment.app.FragmentStateManager.ensureInflatedView(FragmentStateManager.java:392)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:281)
        at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:140)
        at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
        at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:319)
        at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:298)
        at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1067)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:995)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
        at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:699)
        at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195)
        at com.saheralsous.android.MainActivity.onCreate(MainActivity.kt:9)
        at android.app.Activity.performCreate(Activity.java:8000)
E/AndroidRuntime:     at android.app.Activity.performCreate(Activity.java:7984)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        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:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

我没有在主要部分添加或更改任何内容 activity


import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

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

仅在 activity_main 我添加了导航组件的片段

<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"

        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>

我以这种方式初始化片段中的回收视图:

 override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        /**
         * PagingDataAdapter
         */

        RecyclerViewPhotoAdapter = RecyclerViewPhotoAdapter()

        /**
         * Recycler View
          */
        PhotoRecyclerView =
            view?.findViewById(R.id.recyclerview_main) as RecyclerView
        PhotoRecyclerView.layoutManager = LinearLayoutManager(context)

        //linking adapter with recyclerview
        PhotoRecyclerView.adapter = RecyclerViewPhotoAdapter

        /**
         * Adapter, Repository and viewmodel
         */
        pagingAdapter = PhotoPaging(
            (requireActivity().application as MyApplication).networkApi
        )

        repository = GalleryFlowRepositoryImpl(pagingAdapter)

        viewModel = ViewModelProvider(this, ViewModelProviderFactory(
            PhotoGalleryViewModel::class
        ){
            PhotoGalleryViewModel(repository)
        }).get(PhotoGalleryViewModel::class.java)


        //observing data
        observers()
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_photo_gallery, container, false)
    }

fragment_photo_gallery布局就是这样

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".PhotoGalleryFragment">


    <androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerview_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

</FrameLayout>

我发现你的代码有问题。 您在使用 RecyclerView 之前没有填充视图。

PhotoRecyclerView = view?.findViewById(R.id.recyclerview_main) 作为 RecyclerView

在那里,视图应该是空的。因为你没有膨胀视图。 所以要解决你的问题,有两种方法。

首先,在 onCreateView 方法中,您应该在使用前膨胀视图。

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    var view = inflater.inflate(R.layout.fragment_photo_gallery, container, false)
    /**
     * PagingDataAdapter
     */

    RecyclerViewPhotoAdapter = RecyclerViewPhotoAdapter()

    /**
     * Recycler View
      */
    PhotoRecyclerView =
        view?.findViewById(R.id.recyclerview_main) as RecyclerView
    PhotoRecyclerView.layoutManager = LinearLayoutManager(context)

    //linking adapter with recyclerview
    PhotoRecyclerView.adapter = RecyclerViewPhotoAdapter

    /**
     * Adapter, Repository and viewmodel
     */
    pagingAdapter = PhotoPaging(
        (requireActivity().application as MyApplication).networkApi
    )

    repository = GalleryFlowRepositoryImpl(pagingAdapter)

    viewModel = ViewModelProvider(this, ViewModelProviderFactory(
        PhotoGalleryViewModel::class
    ){
        PhotoGalleryViewModel(repository)
    }).get(PhotoGalleryViewModel::class.java)


    //observing data
    observers()
    // Inflate the layout for this fragment
    return view
}

或者其次,您可以在 onViewCreated 方法中使用您的代码。

在您的 onCreateView 中,您在展开布局之前访问视图。

行: PhotoRecyclerView = view?.findViewById(R.id.recyclerview_main) as RecyclerView

您尝试在视图中检索 recyclerview_main,因为此时布局未膨胀。

然后你强制将其转换为 RecyclerViewas RecyclerView 而不是 as? RecyclerView 用于可选转换)导致 NullPointerExcepion.

我建议将您的代码移动到 onViewCreated 方法中。

好的,这不是什么大问题你需要在使用前充气view

首先,将其添加到 onCreateView

的顶部

val view = inflater.inflate(R.layout.fragment_photo_gallery, container, false)

然后return最后查看

return view

希望我的回答对您有所帮助