android崩溃错误:java.lang.IllegalStateException

问题描述 投票:-1回答:1

我有一个包含导航视图的主页仪表板活动。当应用启动时,其行为正常。但是,当我尝试单击导航菜单并打开注释时,我的应用程序崩溃,并显示此错误消息。

java.lang.IllegalStateException: Fragment NoteFragment not attached to a context

以下是我对此的代码。尝试将线性布局管理器添加到noteFragment]中的回收站视图时发生异常

  /**
 * Fundoo Notes
 * @description HomeDashBoardActivity displays all user actions.
 * @file HomeDashBoardActivity.kt
 * @author ksoundarya4
 * @version 1.0
 * @since 07/02/2020
 */
package com.bridgelabz.fundoonotes.note_module.dashboard_page.view

import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.bridgelabz.fundoonotes.R
import com.bridgelabz.fundoonotes.label_module.view.LabelFragment
import com.bridgelabz.fundoonotes.note_module.dashboard_page.model.Note
import com.bridgelabz.fundoonotes.note_module.dashboard_page.viewmodel.DashBoardViewModel
import com.bridgelabz.fundoonotes.note_module.dashboard_page.viewmodel.DashBoardViewModelFactory
import com.bridgelabz.fundoonotes.note_module.note_page.view.AddNoteFragment
import com.bridgelabz.fundoonotes.repository.local_service.DatabaseHelper
import com.bridgelabz.fundoonotes.user_module.login.view.LoginActivity
import com.bridgelabz.fundoonotes.user_module.login.view.toast
import com.bridgelabz.fundoonotes.user_module.registration.model.User
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.navigation.NavigationView

class HomeDashBoardActivity : AppCompatActivity() {

    private val dashBoadViewModelFactory: DashBoardViewModelFactory by lazy {
        DashBoardViewModelFactory(DatabaseHelper(this))
    }
    private val dashBoardViewModel: DashBoardViewModel by lazy {
        ViewModelProvider(this, dashBoadViewModelFactory).get(DashBoardViewModel::class.java)
    }
    private val toolbar: Toolbar by lazy {
        findViewById<Toolbar>(R.id.toolbar)
    }

    private val drawerLayout: DrawerLayout by lazy {
        findViewById<DrawerLayout>(R.id.drawer_layout)
    }

    private val navigationView: NavigationView by lazy {
        findViewById<NavigationView>(R.id.nav_view)
    }

    private val floatingActionButton: FloatingActionButton by lazy {
        findViewById<FloatingActionButton>(R.id.fab)
    }

    private val preferences: SharedPreferences by lazy {
        this.getSharedPreferences(
            "LaunchScreen",
            Context.MODE_PRIVATE
        )
    }
    private lateinit var authenticatedEmail: String
    private var authenticatedUser: User? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home_dash_board)
        setSupportActionBar(toolbar)

        initHomeDashBoardActivity()
        authenticateUser()
        setClickOnFloatingActionButton()
        setNavigationItemClicked()
    }

    private fun authenticateUser() {

        dashBoardViewModel.authenticatedUser(authenticatedEmail)
        dashBoardViewModel.getUser().observe(this, Observer {
            observeUser(it)
        })
    }

    private fun observeUser(user: User?) {
        if (user != null)
            authenticatedUser = user
    }

    private fun initHomeDashBoardActivity() {

        getUserSharedPreferences()
        setActionBarToggle()
        setNoteFragment()
    }

    private fun setNoteFragment() {
        navigationView.setCheckedItem(R.id.nav_home)
        val fragment = NoteFragment()
        replaceFragment(fragment)
    }

    private fun getUserSharedPreferences() {
        val editor = preferences.edit()
        val email = preferences.getString("email", "")
        authenticatedEmail = email!!
        editor.apply()
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.home_dash_board, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.app_bar_user_info -> {
                startUserProfileFragment()
                toast(getString(R.string.tast_when_user_profile_clicked))
                true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }

    override fun onBackPressed() {
        callFragmentsOnBackPressed()
        super.onBackPressed()
    }

    /**Function to set Floating Action Bar when it is clicked*/
    private fun setClickOnFloatingActionButton() {
        floatingActionButton.setOnClickListener {
            val bundle = setNoteArguments()
            replaceAddNoteFragment(bundle)
        }
    }

    private fun setNoteArguments(): Bundle? {
        val bundle = Bundle()
        val note = Note()
        if (authenticatedUser != null)
            note.userId = authenticatedUser!!.id
        bundle.putSerializable(getString(R.string.note), note)
        return bundle
    }

    /**Function to set Navigation Items when they are clicked*/
    private fun setNavigationItemClicked(): Boolean {

        navigationView.setNavigationItemSelectedListener { item ->
            when (item.itemId) {
                R.id.nav_home -> {
                    replaceFragment(NoteFragment())
                    return@setNavigationItemSelectedListener true
                }
                R.id.nav_sing_out -> {
                    onSignOutMenuClick()
                    return@setNavigationItemSelectedListener true
                }
                R.id.nav_archive -> {
                    replaceFragment(ArchiveFragment())
                    return@setNavigationItemSelectedListener true
                }
                R.id.nav_delete -> {
                    replaceFragment(TrashFragment())
                    return@setNavigationItemSelectedListener true
                }
                R.id.nav_label -> {
                    replaceFragment(LabelFragment())
                    return@setNavigationItemSelectedListener true
                }
                R.id.nav_reminder -> {
                    replaceFragment(ReminderFragment())
                    return@setNavigationItemSelectedListener true
                }
                else -> return@setNavigationItemSelectedListener false
            }
        }
        return true
    }

    private fun replaceFragment(fragment: Fragment?) {
        drawerLayout.closeDrawer(navigationView)
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.fragment_container, fragment!!)
        transaction.commit()
    }


    /**Function to set Action Bar Toggle of Drawer Layout*/
    private fun setActionBarToggle() {
        val actionBarDrawerToggle = ActionBarDrawerToggle(
            this,
            drawerLayout,
            toolbar,
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close
        )
        drawerLayout.addDrawerListener(actionBarDrawerToggle)
        actionBarDrawerToggle.syncState()
    }

    /**Function to set alert dialog when SignOut
     * Menu item is clicked */
    private fun onSignOutMenuClick() {
        removePreference()
        signOutAlertDialog()
    }

    private fun removePreference() {
        if (preferences.contains("email")) {
            val editor = preferences.edit()
            editor.clear().apply()
        }
    }

    /**Function that performs sign out alert operation*/
    private fun signOutAlertDialog() {
        val alertDialogBuilder = AlertDialog.Builder(this)

        alertDialogBuilder.setMessage(getString(R.string.sign_out_alert_message))
        alertDialogBuilder.setTitle(getString(R.string.sign_out_alert_title))
        alertDialogBuilder.setCancelable(false)

        alertDialogBuilder
            .setPositiveButton(
                getString(R.string.sign_out_alert_positive_button)
            ) { _, _ ->
                navigateToLoginScreen()
                toast(
                    getString(R.string.toast_when_sign_out_alert_positive_button_clicked)
                )
            }
        alertDialogBuilder.setNegativeButton(getString(R.string.sign_out_alerst_negative_button))
        { dialog, _ ->
            drawerLayout.closeDrawer(navigationView)
            dialog.cancel()
        }

        val alertDialog = alertDialogBuilder.create()
        alertDialog.show()
    }

    /**Function to tell fragment that back navigation is Pressed*/
    private fun callFragmentsOnBackPressed() {
        val fragments: List<Fragment> = supportFragmentManager.fragments
        for (fragment in fragments) {
            if (fragment is OnBackPressed) {
                fragment.onBackPressed()
                setNoteFragment()
            }
        }
    }

    /**Function to replace home dash board with AddNoteFragment*/
    private fun replaceAddNoteFragment(bundle: Bundle?) {
        val fragment = AddNoteFragment()
        fragment.arguments = bundle
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.fragment_container, fragment)
            .addToBackStack(null)
            .commit()
    }

    /**Function to navigate to LoginActivity*/
    private fun navigateToLoginScreen() {
        val intent = Intent(this, LoginActivity::class.java)
        finish()
        startActivity(intent)
    }

    private fun startUserProfileFragment(): Boolean {
        val fragmentManager = supportFragmentManager
        val reminderDialog = UserProfileDialogFragment()
        reminderDialog.arguments = Bundle().apply {
            putSerializable(getString(R.string.authenticated_user), authenticatedUser)
        }
        reminderDialog.show(fragmentManager, getString(R.string.dialog_reminder_title))
        return true
    }
}

这是我的笔记片段

package com.bridgelabz.fundoonotes.note_module.dashboard_page.view

import android.os.Bundle
import android.util.Log
import android.view.*
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.RecyclerView
import com.bridgelabz.fundoonotes.R
import com.bridgelabz.fundoonotes.note_module.dashboard_page.model.Note
import com.bridgelabz.fundoonotes.note_module.dashboard_page.view.recycler_view_strategy.RecyclerViewType
import com.bridgelabz.fundoonotes.note_module.dashboard_page.view.recycler_view_strategy.LinearRecyclerViewManager
import com.bridgelabz.fundoonotes.note_module.dashboard_page.view.recycler_view_strategy.RecyclerViewLayoutManager
import com.bridgelabz.fundoonotes.note_module.dashboard_page.view.recycler_view_strategy.StaggeredRecyclerViewtManager
import com.bridgelabz.fundoonotes.note_module.dashboard_page.viewmodel.NoteTableManagerFactory
import com.bridgelabz.fundoonotes.note_module.dashboard_page.viewmodel.SharedViewModel
import com.bridgelabz.fundoonotes.note_module.note_page.view.AddNoteFragment
import com.bridgelabz.fundoonotes.repository.local_service.DatabaseHelper
import com.bridgelabz.fundoonotes.repository.local_service.note_module.NoteTableManagerImpl

class NoteFragment : Fragment(), OnNoteClickListener {

    private val noteFactory by lazy {
        NoteTableManagerFactory(NoteTableManagerImpl(DatabaseHelper(requireContext())))
    }
    private val sharedViewModel: SharedViewModel by lazy {
        requireActivity().run {
            ViewModelProvider(
                this,
                noteFactory
            ).get(SharedViewModel::class.java)
        }
    }
    private val recyclerView: RecyclerView by lazy {
        requireView().findViewById<RecyclerView>(R.id.notes_recycler_view)
    }

    private lateinit var noteAdapter: NoteViewAdapter

    private lateinit var notes: ArrayList<Note>

    private var recyclerViewType = RecyclerViewType.ListView

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        setHasOptionsMenu(true)
        return inflater.inflate(R.layout.fragment_note, container, false)
    }

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

        sharedViewModel.getRecyclerViewType()
            .observe(requireActivity(), Observer { recyclerViewType = it })
        sharedViewModel.getSimpleNoteLiveData()
            .observe(requireActivity(), Observer { observeNotes(it) })

    }

    private fun initRecyclerView() {
        recyclerView.setHasFixedSize(true)
        recyclerView.layoutManager = setRecyclerViewType(recyclerViewType)
        recyclerView.adapter = noteAdapter
    }

    private fun observeNotes(noteList: ArrayList<Note>) {
        Log.d("noteList", noteList.toString())
        notes = noteList
        noteAdapter = NoteViewAdapter(notes, this)
        noteAdapter.notifyDataSetChanged()
        initRecyclerView()
    }

    override fun onClick(adapterPosition: Int) {
        val note = notes[adapterPosition]
        val bundle = Bundle()
        bundle.putSerializable(getString(R.string.note), note)
        replaceWithAddNoteFragment(bundle)
    }

    override fun onLongClick(adapterPosition: Int) {
        val note = notes[adapterPosition]
        Toast.makeText(requireActivity(), "$note", Toast.LENGTH_SHORT).show()
    }

    private fun replaceWithAddNoteFragment(bundle: Bundle) {
        val addNoteFragment = AddNoteFragment()
        addNoteFragment.arguments = bundle
        requireActivity().supportFragmentManager.beginTransaction()
            .replace(R.id.fragment_container, addNoteFragment).addToBackStack(null).commit()

    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        (requireActivity() as AppCompatActivity).supportActionBar!!.title =
            getString(R.string.menu_notes)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.app_bar_recycler_view -> {
                switchRecyclerViewType()
                switchIcon(item)
                true
            }
            R.id.app_bar_search_note -> {
                val searchView = item.actionView as SearchView
                searchView.setOnQueryTextListener(searchQueryListener)
                true
            }
            else -> false
        }
    }

    private val searchQueryListener = object : SearchView.OnQueryTextListener {
        override fun onQueryTextSubmit(query: String?): Boolean {
            return false
        }

        override fun onQueryTextChange(newText: String?): Boolean {
            noteAdapter.filter.filter(newText)
            return false
        }

    }

    private fun switchIcon(item: MenuItem) {

        if (recyclerViewType == RecyclerViewType.ListView)
            item.setIcon(R.drawable.ic_grid_view_white)
        else {
            item.setIcon(R.drawable.ic_list_view_white)
        }
    }

    private fun switchRecyclerViewType() {

        when (recyclerViewType) {
            RecyclerViewType.GridView -> {
                sharedViewModel.setRecyclerViewType(RecyclerViewType.ListView)
                recyclerView.layoutManager = setRecyclerViewType(recyclerViewType)
            }
            RecyclerViewType.ListView -> {
                sharedViewModel.setRecyclerViewType(RecyclerViewType.GridView)
                recyclerView.layoutManager = setRecyclerViewType(recyclerViewType)
            }
        }
    }

    private fun setRecyclerViewType(viewType: RecyclerViewType): RecyclerView.LayoutManager {
        val layoutManager = RecyclerViewLayoutManager()
        layoutManager.addRecyclerView(recyclerView)

        return when (viewType) {
            RecyclerViewType.ListView -> {
                layoutManager.setRecyclerView(LinearRecyclerViewManager(requireContext()))
            }
            RecyclerViewType.GridView -> {
                layoutManager.setRecyclerView(
                    StaggeredRecyclerViewtManager(
                        numberOfRows = 2,
                        orientation = 1
                    )
                )
            }
        }
    }
}

我有一个包含导航视图的主页仪表板活动。当应用启动时,其行为正常。但是,当我尝试单击导航菜单并打开注释时,我的应用程序崩溃,显示此错误...

android-studio android-fragments kotlin android-recyclerview android-linearlayout
1个回答
0
投票

[您可能按了两次按钮,或者导航呼叫以某种方式触发了两次。

© www.soinside.com 2019 - 2024. All rights reserved.