Welcome back.
Our second improvement is to prevent a task from being deleted
while it's being edited.
That's only possible in landscape.
So run the app then rotate into landscape.
There's nothing to prevent the user from editing a task
then deleting the same task by clicking its button.
We'll add two more tasks so we've got something consistent to look at.
By now you'll probably have a different set of tasks to me,
especially if you've been experimenting with the interface and I hope you have.
I'll call the first new task "Edit me"
and the second one "Delete me".
The description and sort order can be blank for both tasks,
but make sure of course that you hit Save.
Okay. Edit the Edit me task
still in landscape, then click the button to delete
the Delete me task.
Choose Delete from the dialog,
and the task is deleted.
That seems to work fine.
To be sure, enter a description
and hit Save.
That worked fine.
So there's no problem allowing the user to delete one task
while editing another one.
Edit the Edit me task again.
Tap the Delete button
to delete the Edit me task that we're editing
then choose Delete again.
Now the app's in a strange state.
It's editing a task that no longer exists in the database,
and that's probably not going to go too well.
So click Save to check.
Sure enough, we lose any edits that the user may have made.
Data loss is unforgivable,
so we really need to do something about that one.
You may think that the user would be fully aware of what they've done.
We did ask for confirmation of the delete after all.
But there's a big difference between running our apps on an emulator
on a computer monitor and using the apps on a real mobile device.
Users can pass a phone back and forth
and tap things by accident when they do.
So bear that in mind when testing on an emulator.
It's not a true reflection of what happens to a handheld device with a touch screen.
Editing a task is triggered by MainActivityFragment,
that's the same class that responds to the delete button.
So you may think it's going to be easy to track which task is being edited.
Unfortunately, it's not that easy.
MainActivityFragment knows when an edit starts
and can store the task ID somewhere,
but it doesn't know when a task is no longer being edited.
We need some way for AddEditFragment
to communicate with MainActivityFragment.
We're using a ViewModel
and that's the most reliable way to implement fragment
to fragment communication.
In TaskTimerModel, we'll create a read-only attribute
called edited task ID.
I'll put it just before the init block.
Making the set function as private
prevents external code from modifying the attribute.
I'm going to use a pair of functions to change the value.
Getters and setters aren't as common in Kotlin as they are in java,
but they still exist and they have their uses.
I'll paste the function in below the SaveTasks function
then explain why I've used them.
StopEditing is straightforward.
It just sets the edit task ID attribute to zero.
StartEditing includes some code that will only be used in our debug build.
We want to be sure that there isn't a task being edited
when we StartEditing another one.
If we forget to StopEditing a task when the user's finished editing it,
then that's a bug in the logic of our code.
We want to detect that and fix the code if it happens.
Okay. Our AddEditFragment
will tell the ViewModel when it started and stops editing a task.
Let's make that change next.
We only need to do that when editing not when adding a task.
A user can't delete a new task
because it doesn't exist in the RecyclerView,
so there's no delete button to tap.
We StopEditing in the OnDetach function.
Now we can test that value in MainActivityFragment
and display a toast message instead of deleting.
Use the light bulb to extract the text on line 71
and call the resource delete_edited_task.
That's a change completed, and we can test it.
Run the app, and edit the task in landscape.
Then use its delete button to try to delete it.
We get the toast message instead and that's much better.
Make sure you test deleting other tasks
to make sure we haven't broken anything.
There's a very important point to consider here.
Remember back in section 12,
we talked about sharing the ViewModelInstance between the fragments.
It's crucial that you pass the activity
when getting your ViewModelInstances in the fragments.
That's our code
up on line 32.
If each fragment is using its own instance of the ViewModel,
then this communication won't work.
It's important to use by ActivityViewModels here
and in the AddEditFragment class.
If you need to get two or more fragments to communicate with each other,
then doing it via the view model is a great way to achieve that.
You may want to turn this around.
At the moment, we've disabled deleting if a task is being edited.
You may prefer to close the editing pane if the task is deleted.
In that case, AddEditFragment
would observe a LiveData object in the ViewModel
and quietly close itself
if the task it's editing gets deleted.
That may be more appropriate. When creating your apps, you decide how they're going to function.
In the next video, we'll look at removing the delete button from the layout
and we'll implement delete by swiping instead. I'll see you there.