In my last devlog for my productivity app Tempo, I discussed how I had created a CustomView for my Task object, how I would add them directly to my main ConstraintLayout, and how I fixed the layout by using LayoutParams.

In this post, I set out thinking how I was going to discuss implementing the “Add Task” functionality and managing the list of tasks in the MainActivity. However, fate it seems is not without a sense of irony. I knew that I wanted the tasks lined up into some sort of queue where it would start from the last task added and work backwards through the queue while the user is in the “flow state”. With Kotlin as my choice for this project I used a MutableList that holds my custom Task objects.

Creating the MutableList was easy enough by adding the following to the top of the MainActivity class:

private val taskMutableList = mutableListOf<Task>()

In this case taskMutableList is a val because we are creating the MutableList object itself only once and then using its methods to modify it. This way it ensures that we will not keep re-creating, replacing, or throwing away the MutableList every time we want to change the contents.

Once I had that in place and started to think about how I was going to keep track of all the TaskViews on screen and scrolling them etc. etc. I immediately started to look for an improvement to the way I was displaying or managing the view. In comes the ListView (and by extension Adapters) to the rescue.

The ListView connects to an Adapter (such as an ArrayAdapter) that manages/controls access to a specific data source. In my case, I wanted to allow the ListView to display the contents of my taskMutableList and handle all of the layout and spacing for me. Naïvely, I added the ListView to my MainActivity and said something along the lines of:

taskListView.addView(TaskView(Task))

After which the project, unsurprisingly, failed to compile.

Courtesy of knowyourmeme.com

To get it to work I implemented TaskArrayAdapter that extends the default ArrayAdapter and overrides the getView() method in order to return my own TaskView to be displayed in the ListView. The actual TaskArrayAdapter’s getView looks something like this:

override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
    val taskView = TaskView(parent!!.context)
    taskView.populate(getItem(position))
    return taskView
}

Once again, our nifty populate is being used to fill the TaskView easily.

After creating the adapter, all that was left was to connect it to the ListView in the MainActivity by first creating the adapter, and then setting the ListView’s adapter:

listViewAdapter = TaskArrayAdapter(this, R.layout.view_task, taskMutableList)
taskListView.adapter = listViewAdapter

Now all we need to do when we want to update the list is to call notifyDataSetChanged() on our listViewAdapter and the view should automatically update itself. With the new system in place I stress tested it by adding a bunch of tasks and was pleasantly surprised by how nicely it works using Adapters. You can see how it looks below.

Screenshot showing a list of tasks that is scrollable.

Screenshot showing a list of tasks that is scrollable.

Although the layout is not perfect at this stage, it is functionally much better that before. As always, I will post an update when I work on it again, but until then, stay evil.