简体   繁体   中英

Recycler view - on a null object reference

I have bottom sheet view and recycler view in it. It's written in Kotlin. I'm trying to show the list of comments. I get null pointer exception when trying to show the bottom sheet and apply recycler view data. My error is - Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setAdapter(androidx.recyclerview.widget.RecyclerView$Adapter)' on a null object reference. Other answers don't help. Here is my fragment -

class AudioFragment : Fragment(R.layout.fragment_audio) {

    @Inject
    lateinit var glide: RequestManager

    lateinit var bottomSheetDialog: BottomSheetDialog
    lateinit var bottomSheetView: View

    @Inject
    lateinit var commentAdapter: CommentAdapter

    private lateinit var mainViewModel: MainViewModel
    private val audioViewModel: AudioViewModel by viewModels()

    private var curPlayingAudio: Audio? = null

    private var playbackState: PlaybackStateCompat? = null

    private var shouldUpdateSeekbar = true

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

        bottomSheetDialog = BottomSheetDialog(requireContext(), R.style.BottomSheetDialogTheme)

        bottomSheetView = LayoutInflater.from(requireContext()).inflate(R.layout.bottom_sheet_comment, null)
        bottomSheetDialog.setContentView(bottomSheetView)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mainViewModel = ViewModelProvider(requireActivity()).get(MainViewModel::class.java)
        subscribeToObservers()

        ivPlayPauseDetail.setOnClickListener {
            curPlayingAudio?.let {
                mainViewModel.playOrToggleAudio(it, true)
            }
        }

        arrowBack.setOnClickListener {
            navHostFragment.findNavController().navigate(
                    R.id.globalActionFromAudioFragmentToHome
            )
        }

        seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                if(fromUser) {
                    setCurPlayerTimeToTextView(progress.toLong())
                }
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {
                shouldUpdateSeekbar = false
            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
                seekBar?.let {
                    mainViewModel.seekTo(it.progress.toLong())
                    shouldUpdateSeekbar = true
                }
            }
        })

        ivSkipPrevious.setOnClickListener {
            mainViewModel.skipToPreviousAudio()
        }

        ivSkip.setOnClickListener {
            mainViewModel.skipToNextAudio()
        }

        commentOpen.setOnClickListener {
            bottomSheetDialog.show()

            rvAllComments.apply {
                adapter = commentAdapter
                layoutManager = LinearLayoutManager(requireContext())
            }
            curPlayingAudio?._id?.let { it1 ->
                RetrofitService().getComments(it1).enqueue(object: Callback<List<Comment>> {
                    override fun onFailure(call: Call<List<Comment>>, t: Throwable) {
                        Log.d("err", "${t.message}")
                        Toast.makeText(requireContext(), t.message, Toast.LENGTH_LONG).show()
                    }

                    override fun onResponse(call: Call<List<Comment>>, response: Response<List<Comment>>) {
                        allCommentsProgressBar.visibility = INVISIBLE
                        response.body()?.let { res ->
                            commentAdapter.comments = res
                        }
                    }
                })
            }
        }
    }

    private fun updateTitleAndAudioImage(audio: Audio) {
        val title = "${audio.title}"
        val writer = "${audio.writer.name}"
        tvAudioName.text = title
        tvAudioWriter.text = writer
        glide.load(audio.writer.image).into(ivAudioImage)
    }

    private fun subscribeToObservers() {
        mainViewModel.mediaItems.observe(viewLifecycleOwner) {
            it.let { result ->
                when(result.status) {
                    SUCCESS -> {
                        result.data?.let { audios ->
                            if(curPlayingAudio == null && audios.isNotEmpty()) {
                                curPlayingAudio = audios[0]
                                updateTitleAndAudioImage(audios[0])
                            }
                        }
                    }
                    else -> Unit
                }
            }
        }
        mainViewModel.curPlayingAudio.observe(viewLifecycleOwner) {
            if(it == null) return@observe
            curPlayingAudio = it.toAudio()
            updateTitleAndAudioImage(curPlayingAudio!!)
        }
        mainViewModel.playbackState.observe(viewLifecycleOwner) {
            playbackState = it
            ivPlayPauseDetail.setImageResource(
                if(playbackState?.isPlaying == true) R.drawable.ic_pause else R.drawable.ic_play_arrow
            )
            seekBar.progress = it?.position?.toInt() ?: 0
        }
        audioViewModel.curPlayerPosition.observe(viewLifecycleOwner) {
            if(shouldUpdateSeekbar) {
                seekBar.progress = it.toInt()
                setCurPlayerTimeToTextView(it)
            }
        }
        audioViewModel.curAudioDuration.observe(viewLifecycleOwner) {
            seekBar.max = it.toInt()
            val dateFormat = SimpleDateFormat("mm:ss", Locale.getDefault())
            tvAudioDuration.text = dateFormat.format(it)
        }
    }

    private fun setCurPlayerTimeToTextView(ms: Long) {
        val dateFormat = SimpleDateFormat("mm:ss", Locale.getDefault())
        tvCurTime.text = dateFormat.format(ms)
    }
}

Here is my bottom sheet view -

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/bottomSheet"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bottom_sheet_background"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical">

    <TextView
        android:id="@+id/commentsHeader"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Comments"
        android:padding="10dp"
        android:gravity="center"
        android:textStyle="bold"
        android:textSize="18sp"/>

    <View
        android:id="@+id/commentsHeaderHr"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#7A7A7A"
        android:layout_marginBottom="10dp" />

    <ProgressBar
        android:id="@+id/allCommentsProgressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvAllComments"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>

Try

bottomsheetview.rvAllComments.apply

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