Reputation: 119
I have an app where one functionality is that you can choose a day of the week by clicking on it's cardview.
My current problem is that if you do the following sequence, you get an unexpected result:
Clear -> pick day -> add task -> submit -> back button to Main Activity
When you do this sequence, the db is cleared again unexpectedly after the initial clearing, or if you go to a day, add a task, and navigate back, it runs again and/or puts you back in the view of the day you just left.
What I have noticed and what I have tried:
The foreach
loop I have does what it's supposed to: flip through the weekdays until it hits the right one...but then it does it again? I know it's happening too much from logs and from the Toast
popping up again after it's finished (it says db cleared automatically followed by there's nothing to clear). Also I have tried to add breakpoints within the foreach loop, but I don't think that helps me as it only breaks the iteration of the loop that one time if I'm not mistaken?
I have tried an activity level boolean variable to make it stop and start when I need, but the problem ends up being that I then either need to press any given card twice, it doesn't do anything at all after the first item is chosen, or the problem remains the same.
I've used onClick in the xml for the button listeners, but I've also tried it programmed into the activity kotlin class and it didn't make a difference
Maybe I'm just missing an extra iteration of a loop somewhere, or a break in the proper place?
Main Activity XML
<?xml version="1.0" encoding="utf-8"?>
<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" >
<TextView
android:id="@+id/top_box"
android:layout_width="0dp"
android:layout_height="90dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<com.google.android.material.card.MaterialCardView
android:id="@+id/clear_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
android:onClick="buttonClick"
app:layout_constraintTop_toBottomOf="@id/top_box"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/sunday_card"
app:layout_constraintBottom_toTopOf="@id/wednesday_card">
<TextView
android:id="@+id/clear_card_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:gravity="center"
/>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/sunday_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
android:onClick="buttonClick"
app:layout_constraintTop_toBottomOf="@+id/top_box"
app:layout_constraintLeft_toRightOf="@id/clear_card"
app:layout_constraintRight_toLeftOf="@id/monday_card"
app:layout_constraintBottom_toTopOf="@id/thursday_card">
<TextView
android:id="@+id/sunday_card_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:gravity="center"/>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/monday_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
android:onClick="buttonClick"
app:layout_constraintTop_toBottomOf="@id/top_box"
app:layout_constraintLeft_toRightOf="@id/sunday_card"
app:layout_constraintRight_toLeftOf="@id/tuesday_card"
app:layout_constraintBottom_toTopOf="@id/friday_card">
<TextView
android:id="@+id/monday_card_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:gravity="center"/>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/tuesday_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
android:onClick="buttonClick"
app:layout_constraintTop_toBottomOf="@id/top_box"
app:layout_constraintLeft_toRightOf="@id/monday_card"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/saturday_card">
<TextView
android:id="@+id/tuesday_card_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:gravity="center"/>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/wednesday_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
android:onClick="buttonClick"
app:layout_constraintTop_toBottomOf="@id/clear_card"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/thursday_card"
app:layout_constraintBottom_toTopOf="@id/bottom_box">
<TextView
android:id="@+id/wednesday_card_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:gravity="center"/>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/thursday_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
android:onClick="buttonClick"
app:layout_constraintTop_toBottomOf="@id/sunday_card"
app:layout_constraintLeft_toRightOf="@id/wednesday_card"
app:layout_constraintRight_toRightOf="@id/friday_card"
app:layout_constraintBottom_toTopOf="@id/bottom_box">
<TextView
android:id="@+id/thursday_card_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:gravity="center"/>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/friday_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
android:onClick="buttonClick"
app:layout_constraintTop_toBottomOf="@id/monday_card"
app:layout_constraintLeft_toRightOf="@id/thursday_card"
app:layout_constraintRight_toLeftOf="@id/saturday_card"
app:layout_constraintBottom_toTopOf="@id/bottom_box">
<TextView
android:id="@+id/friday_card_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:gravity="center"/>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/saturday_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
android:onClick="buttonClick"
app:layout_constraintTop_toBottomOf="@id/tuesday_card"
app:layout_constraintLeft_toRightOf="@id/friday_card"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/bottom_box">
<TextView
android:id="@+id/saturday_card_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:gravity="center"/>
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/bottom_box"
android:layout_width="0dp"
android:layout_height="90dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val plannerViewModel: PlannerViewModel by viewModels {
PlannerViewModelFactory((application as PlannerApplication).repository)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val clearButtonText = binding.clearCardText
val sundayButtonText = binding.sundayCardText
val mondayButtonText = binding.mondayCardText
val tuesdayButtonText = binding.tuesdayCardText
val wednesdayButtonText = binding.wednesdayCardText
val thursdayButtonText = binding.thursdayCardText
val fridayButtonText = binding.fridayCardText
val saturdayButtonText = binding.saturdayCardText
// Setting day card names
clearButtonText.text = "Clear"
sundayButtonText.text = "Sun"
mondayButtonText.text = "Mon"
tuesdayButtonText.text = "Tue"
wednesdayButtonText.text = "Wed"
thursdayButtonText.text = "Thu"
fridayButtonText.text = "Fri"
saturdayButtonText.text = "Sat"
sundayButtonText.text = "Sun"
}
private fun startWeekdayActivity(day: Weekday) {
val intent = Intent(this, WeekdayActivity::class.java)
intent.putExtra("dayId", day.id)
this.startActivity(intent)
}
private fun clearDb() {
val alertDialog: AlertDialog? = this?.let { outerIt ->
val builder = AlertDialog.Builder(outerIt)
builder.apply {
setPositiveButton("Clear",
DialogInterface.OnClickListener { dialog, id ->
plannerViewModel.allTasks.observe(outerIt, {
if (it.count() == 0) {
Toast.makeText(context, "No tasks to clear", Toast.LENGTH_SHORT).show()
}
else {
plannerViewModel.deleteAllTasks()
Toast.makeText(context, "Tasks cleared", Toast.LENGTH_SHORT).show()
}
})
})
setNegativeButton("Cancel",
DialogInterface.OnClickListener { dialog, id ->
// User cancelled the dialog
})
}
.setTitle("Clear tasks?")
.setMessage("Are you sure you want to clear the weeks tasks?")
// Create the AlertDialog
builder.create()
}
alertDialog?.show()
}
private fun checkDay(dayIn: String) {
var dayOut: Weekday? = null
plannerViewModel.allWeekdays.observe(this, { weekdays ->
weekdays?.let {
weekdays.forEach {
if (dayIn == "clear_card" && it.day == "Clear") {
clearDb()
dayOut = it
}
else {
val dayInAbr = dayIn.substring(0, 3).toLowerCase(Locale.ROOT)
val dayOutAbr = it.day.substring(0,3).toLowerCase(Locale.ROOT)
if (dayInAbr == dayOutAbr) {
dayOut = it
dayOut?.let { startWeekdayActivity(it) }
}
}
if (dayOut != null) {
return@let
}
}
}
})
}
fun buttonClick(view: View) {
when(view.id) {
R.id.clear_card -> checkDay(view.context.resources.getResourceEntryName(R.id.clear_card).toString())
R.id.sunday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.sunday_card).toString())
R.id.monday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.monday_card).toString())
R.id.tuesday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.tuesday_card).toString())
R.id.wednesday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.wednesday_card).toString())
R.id.thursday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.thursday_card).toString())
R.id.friday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.friday_card).toString())
R.id.saturday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.saturday_card).toString())
}
}
}
Upvotes: 1
Views: 204
Reputation: 119
Question answered by Jay in the comments
If you know a way for me to credit them for the SO points and reputation, let me know!
I needed to stop calling more instances of observer every time checkDay()
ran. Moving the observers to onCreate()
so that they only run one time seems to have fixed my issue!
Working Code for Main Activity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val plannerViewModel: PlannerViewModel by viewModels {
PlannerViewModelFactory((application as PlannerApplication).repository)
}
lateinit var weekdayList: List<Weekday>
lateinit var taskList: List<Task>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val clearButtonText = binding.clearCardText
val sundayButtonText = binding.sundayCardText
val mondayButtonText = binding.mondayCardText
val tuesdayButtonText = binding.tuesdayCardText
val wednesdayButtonText = binding.wednesdayCardText
val thursdayButtonText = binding.thursdayCardText
val fridayButtonText = binding.fridayCardText
val saturdayButtonText = binding.saturdayCardText
// Setting day card names
clearButtonText.text = "Clear"
sundayButtonText.text = "Sun"
mondayButtonText.text = "Mon"
tuesdayButtonText.text = "Tue"
wednesdayButtonText.text = "Wed"
thursdayButtonText.text = "Thu"
fridayButtonText.text = "Fri"
saturdayButtonText.text = "Sat"
sundayButtonText.text = "Sun"
plannerViewModel.allTasks.observe(this, {
taskList = it
})
plannerViewModel.allWeekdays.observe(this, {
weekdayList = it
})
}
private fun startWeekdayActivity(day: Weekday) {
val intent = Intent(this, WeekdayActivity::class.java)
intent.putExtra("dayId", day.id)
this.startActivity(intent)
}
private fun clearDb(taskList: List<Task>) {
val alertDialog: AlertDialog? = this?.let { outerIt ->
val builder = AlertDialog.Builder(outerIt)
builder.apply {
setPositiveButton("Clear",
DialogInterface.OnClickListener { dialog, id ->
if (taskList.count() == 0) {
Toast.makeText(context, "No tasks to clear", Toast.LENGTH_SHORT).show()
} else {
plannerViewModel.deleteAllTasks()
Toast.makeText(context, "Tasks cleared", Toast.LENGTH_SHORT).show()
}
})
setNegativeButton("Cancel",
DialogInterface.OnClickListener { dialog, id ->
// User cancelled the dialog
})
}
.setTitle("Clear tasks?")
.setMessage("Are you sure you want to clear the weeks tasks?")
builder.create()
}
alertDialog?.show()
}
private fun checkDay(dayIn: String, weekdayList: List<Weekday>) {
weekdayList.forEach {
if (dayIn == "clear_card" && it.day == "Clear") {
clearDb(taskList)
} else {
val dayInAbr = dayIn.substring(0, 3).toLowerCase(Locale.ROOT)
val dayOutAbr = it.day.substring(0, 3).toLowerCase(Locale.ROOT)
if (dayInAbr == dayOutAbr) {
startWeekdayActivity(it)
}
}
}
}
fun buttonClick(view: View) {
when (view.id) {
R.id.clear_card -> checkDay(view.context.resources.getResourceEntryName(R.id.clear_card).toString(), weekdayList)
R.id.sunday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.sunday_card).toString(), weekdayList)
R.id.monday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.monday_card).toString(), weekdayList)
R.id.tuesday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.tuesday_card).toString(), weekdayList)
R.id.wednesday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.wednesday_card).toString(), weekdayList)
R.id.thursday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.thursday_card).toString(), weekdayList)
R.id.friday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.friday_card).toString(), weekdayList)
R.id.saturday_card -> checkDay(view.context.resources.getResourceEntryName(R.id.saturday_card).toString(), weekdayList)
}
}
}
Upvotes: 1