E/RecyclerView: No adapter attached; skipping layout(Kotlin) - android-studio

I have a trouble with a error "E/RecyclerView: No adapter attached; skipping layout" for 2 days...
Please help me what causes this error...
I already checked that getItemCount function return 1 result(Because the ProductEntity database only have 1 data)
Thank you in advance!!
[ProductActivity.kt]
package com.example.trymakeapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.trymakeapp.databinding.ActivityProductBinding
import com.example.trymakeapp.databinding.ItemProductBinding
import com.example.trymakeapp.db.AppDatabase
import com.example.trymakeapp.db.ProductDao
import com.example.trymakeapp.db.ProductEntity
class ProductActivity : AppCompatActivity() {
private lateinit var binding: ActivityProductBinding
private lateinit var db: AppDatabase
private lateinit var productDao: ProductDao
private lateinit var productList : ArrayList<ProductEntity>
private lateinit var adapter : ProductRecyclerViewAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityProductBinding.inflate(layoutInflater)
setContentView(binding.root)
db = AppDatabase.getInstance(this)!!
productDao = db.getProductDao()
getAllProductList()
}
private fun getAllProductList() {
Thread {
productList = ArrayList(productDao.getAll())
setRecyclerView()
}.start()
println("#####")
}
private fun setRecyclerView() {
runOnUiThread {
adapter = ProductRecyclerViewAdapter(productList)
binding.recyclerView.adapter = adapter
binding.recyclerView.layoutManager = LinearLayoutManager(this#ProductActivity)
}
}
}
[ProductRecyclerViewAdapter.kt]
package com.example.trymakeapp
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.trymakeapp.databinding.ItemProductBinding
import com.example.trymakeapp.db.ProductEntity
import java.util.ArrayList
class ProductRecyclerViewAdapter(private val productList : ArrayList<ProductEntity>)
: RecyclerView.Adapter<ProductRecyclerViewAdapter.MyViewHolder>() {
inner class MyViewHolder(binding: ItemProductBinding) :
RecyclerView.ViewHolder(binding.root) {
val product_idx = binding.productIdx
val product_name = binding.productName
val product_price = binding.productPrice
val product_img = binding.productImg
val root = binding.root
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val binding : ItemProductBinding =
ItemProductBinding.inflate(LayoutInflater.from(parent.context),
parent, false)
return MyViewHolder(binding)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val productData = productList[position]
holder.product_idx.text = productData.idx
holder.product_name.text = productData.name
holder.product_price.text = productData.price.toString()
}
override fun getItemCount(): Int {
return productList.size
}
}
[MainActivity.kt]
...
...
btn3.setOnClickListener {
val intent = Intent(this, ProductActivity::class.java)
startActivity(intent)
}

Try to move the initialization in the onCreate method:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityProductBinding.inflate(layoutInflater)
setContentView(binding.root)
db = AppDatabase.getInstance(this)!!
productDao = db.getProductDao()
binding.recyclerView.layoutManager = LinearLayoutManager(this)
adapter = ProductRecyclerViewAdapter(arrayListOf())
binding.recyclerView.adapter = adapter
getAllProductList()
}
And edit your setRecyclerView method like this (You can remove the adapter and productList global variables):
private fun setRecyclerView(productList: ArrayList<ProductEntity>) {
runOnUiThread {
binding.recyclerView.adapter = ProductRecyclerViewAdapter(productList)
}
}
EDIT
To handle the fact that data are not displayed. Try to use LiveData to observe its changes:
#Dao
interface ProductDao {
#Query("select * from ProductEntity")
fun getAll() : LiveData<List<ProductEntity>>
}
Then observe changes in the getAll method using observe:
private fun getAllProductList() {
productDao.getAll().observe(this) {
setRecyclerView(ArrayList(it))
}
}

Related

ViewModelProvider not taking "this" (MainActivity) as its owner in kotlin Android Studios

I am trying to communicate between MainActivity.kt and sharedviewmodel.kt which is of type viewModel() for WearOS, But when i try to create an instance of the sharedviewmodel.kt in MainActivity.kt by below lines
private lateinit var viewModel: sharedviewmodel
viewModel = ViewModelProvider(this).get(sharedviewmodel::class.java)
when i pass "this" as owner of the ViewModelProvider, i face a error called
Required : ViewModelStoreOwner
Found : MainActivity
Kindly someone help to solve the issue,
Find the MainActivity.kt and sharedviewmodel.kt below.
import android.app.Activity
import android.os.Bundle
import android.util.Log
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.watch7_view_model_example.databinding.ActivityMainBinding
class MainActivity : Activity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: sharedviewmodel
var tag = "view_model"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
viewModel = ViewModelProvider(this).get(sharedviewmodel::class.java)
viewModel.azimuth().observe(this, Observer {
Log.d(tag,"data")
})
}
}
sharedviewmodel.kt
package com.example.watch7_view_model_example
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class sharedviewmodel:ViewModel() {
private val azimuth: MutableLiveData<String> = MutableLiveData()
private val elevation: MutableLiveData<String> = MutableLiveData()
fun azimuth(): LiveData<String> = azimuth
fun elevation(): LiveData<String> = elevation
fun azimuth(azimuth_t: String) {
azimuth.value = azimuth_t
}
fun elevation(elevation_t: String) {
elevation.value = elevation_t
}
init {
// Setting default value
azimuth.value = "0"
elevation.value = "0"
}
}`

Kotlin E/RecyclerView: No adapter attached; skipping layout (Adapter doesnt work)

I am using RecyclerView in my app. But I'm getting this error in the Logcat. Here is my Codes;
My Fragment
package com.ahmetkaan.kediy.Fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.ahmetkaan.kediy.R
import com.ahmetkaan.kediy.adapter.NotesAdapter
import com.ahmetkaan.kediy.database.NotesDatabase
import com.ahmetkaan.kediy.databinding.FragmentHomeBinding
import com.ahmetkaan.kediy.entities.Notlar
import kotlinx.coroutines.launch
import java.util.*
import kotlin.collections.ArrayList
class Home : BaseFragment() {
lateinit var binding : FragmentHomeBinding
var arrNotes = ArrayList<Notlar>()
var notesAdapter: NotesAdapter = NotesAdapter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentHomeBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.recyclerView.setHasFixedSize(true)
binding.recyclerView.layoutManager = StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL)
launch {
context?.let {
val notes = NotesDatabase.getDatabase(it).noteDao().getAllNotes()
notesAdapter.setData(notes)
arrNotes = notes as ArrayList<Notlar>
binding.recyclerView.adapter = notesAdapter
}
}
binding.searchView.setOnQueryTextListener( object : SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(p0: String?): Boolean {
return true
}
override fun onQueryTextChange(p0: String?): Boolean {
var tempArr = ArrayList<Notlar>()
for (arr in arrNotes){
if (arr.not!!.toLowerCase(Locale.getDefault()).contains(p0.toString())){
tempArr.add(arr)
}
}
notesAdapter.setData(tempArr)
notesAdapter.notifyDataSetChanged()
return true
}
})
notesAdapter.setOnClickListener(onClicked)
binding.notEkle.setOnClickListener {
val action = HomeDirections.actionHome2ToNotOlustur()
Navigation.findNavController(requireActivity(), R.id.fragmentContainerView).navigate(action)
}
binding.calendar.setOnClickListener {
val action = HomeDirections.actionHome2ToCalendar2()
Navigation.findNavController(requireActivity(), R.id.fragmentContainerView).navigate(action)
}
}
private val onClicked = object :NotesAdapter.OnItemClickListener {
override fun onClicked(notesId: Int) {
val fragment: Fragment
val bundle = Bundle()
bundle.putInt("noteId", notesId)
fragment = NotOlustur.newInstance()
fragment.arguments = bundle
val action = HomeDirections.actionHome2ToNotOlustur()
Navigation.findNavController(requireActivity(), R.id.fragmentContainerView)
.navigate(action)
}
}
}
My Adapter
package com.ahmetkaan.kediy.adapter
import android.graphics.BitmapFactory
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.cardview.widget.CardView
import androidx.core.graphics.drawable.toDrawable
import androidx.recyclerview.widget.RecyclerView
import com.ahmetkaan.kediy.R
import com.ahmetkaan.kediy.entities.Notlar
import kotlin.collections.ArrayList
class NotesAdapter() :
RecyclerView.Adapter<NotesAdapter.NotesViewHolder>() {
var listener:OnItemClickListener? = null
var arrList = ArrayList<Notlar>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotesViewHolder {
return NotesViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_notlar,parent,false)
)
}
override fun getItemCount(): Int {
return arrList.size
}
fun setData(arrNotesList: List<Notlar>){
arrList = arrNotesList as ArrayList<Notlar>
}
fun setOnClickListener(listener1: OnItemClickListener){
listener = listener1
}
override fun onBindViewHolder(holder: NotesViewHolder, position: Int) {
holder.itemView.findViewById<TextView>(R.id.theNotC).text = arrList[position].not
holder.itemView.findViewById<TextView>(R.id.dateTimeC).text = arrList[position].dateTime
if (arrList[position].impPathBackground != null){
holder.itemView.findViewById<ImageView>(R.id.backgroundC).setImageBitmap(BitmapFactory.decodeFile(arrList[position].impPathBackground))
} else {
holder.itemView.findViewById<ImageView>(R.id.backgroundC).setImageDrawable(R.drawable.ronin.toDrawable())
}
if (arrList[position].impPathBackground != null){
holder.itemView.findViewById<ImageView>(R.id.backgroundC).setImageBitmap(BitmapFactory.decodeFile(arrList[position].impPathLogo))
} else {
holder.itemView.findViewById<ImageView>(R.id.backgroundC).setImageDrawable(R.drawable.logo1.toDrawable())
}
holder.itemView.findViewById<CardView>(R.id.cardView).setOnClickListener {
listener!!.onClicked(arrList[position].id!!)
}
}
class NotesViewHolder(view:View) : RecyclerView.ViewHolder(view){
}
interface OnItemClickListener{
fun onClicked(noteId:Int)
}
}
I searched a lot on the internet but I didn't understand much because they are all in java language. It didn't work even though I tried what I understood. Unlike others, I used CoroutineScope(launch) I think it was because of it, but I'm not sure. What should i do?
Setting the adapter should be in the main thread. But you wrapped it in launch.
binding.recyclerView.adapter = notesAdapter

Details in the Second activity with OnClickListener

I need help, I need that when you click for each cell of RecyclerView after clicking it and switching to a new activity using onclick on this activity, the name of the object and detailed information was appearing, if there are ideas how this can be done on Kotlin without a database(I managed to transfer the name using intent.putExtra)
Photo code
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity(),onClick {
private var recyclerView: RecyclerView? = null
private var item: ArrayList<Item>? = null
private var gridLayoutManager: GridLayoutManager? = null
private var adapter: Adapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView = findViewById(R.id.item_list)
//количество grid элементов в строчке
gridLayoutManager =
GridLayoutManager(applicationContext, 2,
LinearLayoutManager.VERTICAL, false)
recyclerView?.layoutManager = gridLayoutManager
recyclerView?.setHasFixedSize(true)
item = ArrayList()
item = setItem()
//установка адаптера
adapter = Adapter(item!!,this)
recyclerView?.adapter = adapter
item_list.adapter=adapter
}
private fun setItem(): ArrayList<Item> {
//добавление элементов в RecyclerView
var arrayList: ArrayList<Item> = ArrayList()
arrayList.add(Item(R.drawable.koscmos, "A Latter"))
arrayList.add(Item(R.drawable.teatr, "B Latter"))
arrayList.add(Item(R.drawable.bridge, "C Latter"))
return arrayList
}
override fun onItemClick(position: Int) {
Toast.makeText(this,"id" +position,Toast.LENGTH_LONG).show()
//переход на новую активность с переносом названия в эту активность
val intent= Intent(this,secondAct::class.java)
intent.putExtra("name", item?.get(position)?.name)
startActivity(intent)
}
}
Adapter:
class Adapter(var arrayList: ArrayList<Item>, private val onClick: onClick) :
RecyclerView.Adapter<Holder>() {
//Установка холдера
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val viewHolder = LayoutInflater.from(parent.context)
.inflate(R.layout.item_list, parent, false)
return Holder(viewHolder)
}
override fun getItemCount(): Int {
return arrayList.size
}
override fun onBindViewHolder(holder: Holder, position: Int) {
//установка элементов для onClick
val item: Item = arrayList[position]
holder.icons.setImageResource(item.icons!!)
holder.titles.text = item.name
holder.icons.setOnClickListener {
onClick.onItemClick(position)
}
holder.titles.setOnClickListener {
onClick.onItemClick(position)
}
}
}
class Item : Serializable {}
now You can pass the object through Intent :
override fun onItemClick(position: Int) {
val intent= Intent(this,secondAct::class.java)
intent.putExtra("item", item?.get(position))
startActivity(intent)
}
then in secondAct
val item = intent.extras.get("item") as Item

Interface OnSeekBarChangeListner does not have constructor / No members to implement have been found

[![Not able to implement Menbers`package com.manan.musicx
import android.content.Context
import android.media.AudioManager
import android.media.MediaPlayer
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Button
import android.widget.MediaController
import android.widget.SeekBar
class MainActivity : AppCompatActivity() {
lateinit var btnPlay: Button
lateinit var btnPause: Button
lateinit var btnStop: Button
lateinit var player: MediaPlayer
lateinit var sbVolume: SeekBar
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnPlay = findViewById(R.id.btnPlay)
btnPause = findViewById(R.id.btnPause)
btnStop = findViewById(R.id.btnStop)
sbVolume = findViewById(R.id.sbVolume)
val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
player = MediaPlayer.create(this#MainActivity, R.raw.music)
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
val curVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
sbVolume.setMax(maxVolume)
sbVolume.setProgress(curVolume)
sbVolume.setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener())
// Play function, play set on click listner
btnPlay.setOnClickListener {
player.start()
}
// Pause function, pause set on click listner
btnPause.setOnClickListener {
player.pause()
}
// Stop function, stop set on click listner
btnStop.setOnClickListener {
player.stop()
}
}
}`]1]1
You should write the Seekbar.OnSeekBarChangeListener as:
sbVolume.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
//onProgressChanged
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
//onStartTrackingTouch
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
//onStopTrackingTouch
}
})
or create a class implementing SeekBar.OnSeekBarChangeListener as:
private class MySeekbarChangeListener : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
//onProgressChanged
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
//onStartTrackingTouch
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
//onStopTrackingTouch
}
}
and use it as:
sbVolume.setOnSeekBarChangeListener(MySeekbarChangeListener())

android crash error: java.lang.IllegalStateException

I have a home dash board activity containing navigation view. when the app starts it behaves normally. but when i try to click on navigation menu and open notes my app crashes showing this error message.
java.lang.IllegalStateException: Fragment NoteFragment not attached to a context
Below is my code regarding this. the exception occurs when trying to add LinearLayoutManager to recycler view in 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
}
}
This is my note fragment
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
)
)
}
}
}
}
There's likely that you are pressing twice the button or somehow the navigate call triggers twice.

Resources