1. Home
  2. Training Library
  3. Programming
  4. Programming Courses
  5. Building a To Do List App in Android

Building a To Do List App in Android


Building a To Do List

The course is part of this learning path

Building a To Do List App in Android

In this course, we develop an Android application named To Do List. You will follow along as we build an app that allows you to add tasks to a list, save the data to device memory and read the data back.

Intended Audience

This course is intended for anyone who wants to learn how to start building their own apps on Android.


To get the most out of this course, you should have some basic knowledge of the fundamentals of Android.


Course GitHub repo: https://github.com/OakAcademy/android-app-development-with-kotlin/tree/main/Section%209%20-To-Do%20List%20Project/ToDoList 


Well. Hello everyone. So, today we're going to create a new project. All right. So, in this video, we're going to do a project and it's going to be a To Do List. Now, you can add something that you want to remember to do right in this list. One of the most important things on this project, you're going to learn how to save data in the device memory and how to read this data back. All right. It might seem a little similar, but like I said, practice is, well, practice. It's also how we learn. So, after finishing the project, we're also going to show how to create an APK file, how to publish this project on Google Play. And I promise you that at the beginning. So, congratulations for making it this far.

Let's keep going. So, this is what our project is going to look like. We're going to go to Android Studio now and before we start, I will show you what it will be when you're done. So, this here's our application. If you want to add a new item to the list, was right you just write it in here and click the 'ADD' button. After you click the button, boom, it gets added to the list. So, for example, I'll just write in here, go to office, I'll click the 'Add' button, and see that the new item is added to the list. Also after adding the item, the edit text is cleared. So, the important thing here is when I close the application, the list is not going to be deleted. All the items will get saved to the device's memory. You want to try it out? All right, let's do it. I'm going to close the application, open it up again. Also, I do want to mention another thing, all the applications that we created were looking into the device with this Android robot icon. But this time, our application is going to have a new logo. So, when I open up the application again, cool, the list is the same. Everything comes back. We didn't lose anything. And I do want to point out another feature on the application; when you click on an item on the list, it's going to ask you you want to delete this item? If you click 'YES', it will delete the item from the list. If you click 'NO', it's not going to delete the item from the list. But also you should know this. The application is working slowly, because it's working on this virtual device. If you run this application on real device, it's not going to be that slow, promises, truly. All right, let's get to it. So, first, I want to create a New Project. This project will be for Phones and Tablets. So, I select Empty Activity, click 'Next'. I'll give a name to this project and the name can be To Do List. All right. So, Android Studio gives a package name automatically.

Now, I can select where to save this project from here but default is okay for me. Programming language Kotlin. Minimum API, let's make it 16. So, that means that my app is going to work on 99.8% of all Android devices in the marketplace. So, after I click 'Finish', Android Studio will create a new project for me. All right, so now, the new project's ready, it's an empty project. So, first let's open the activity_main.xml file. So, you see there's an icon here looks like an eye. If you click this icon and select 'Show System UI', you can see how the layout design is going to look on the device. All right. So, I'm going to close my old project and also I'm going to delete this TextView. So, let's start to design our application. Now, if you look at this application, there's an edit text to enter items. There's a button next to the edit text. There is a ListView to show the list. So, when we click on the 'ADD' button, the item will be added to the ListView. You know how it works.

So, I'm going to delete this ConstraintLayout on the XML side. You can continue with a ConstraintLayout if you want. I will write LinearLayout instead of ConstraintLayout. Also, I'm going to define the orientation property of this LinearLayout to be vertical. I'll add another LinearLayout under this  LinearLayout and this time it's going to be horizontal. I'll add one text edit and one button under this horizontal LinearLayout. I'll change the layout_height of this horizontal layout to wrap_content. It's very important that you make this change as well my friends. If the height of this layout is match_parent, even if you add items to the ListView component, you won't be able to see the items that you added on the screen. Why? Because horizontal linear layout, that's going to cover the entire screen. Also, I'm going to change the layout_height property of the edit text to 50dp. I'll also change the weight of this edit text and I will write 4, and the way it will be just for the  one button. So, that means I've divided this layout 5five times and given four pieces to the edit text and one piece to the button. So now, I can change the text of the button. All right. Add, also, I'll delete the text of the edit text and I'll add a hint. All right. Add To Do... All right. So, I will select the italic type from the textStyle property. And also add some space to this layout. So, I'll go to the layout_margin and write 5dp. That means that I've left 5dp space from 4 sides of the layout. And then lastly, I'll select the 'editText add button' and I will change the layout_margin property of these two components.

So, I'm going to write 3dP. Okay, so that's just fine. Now, I'm going to add a ListView. This will be under the vertical layout. I will check ids of these component. So, the id of the EditText is editText, id of the button is button, id of ListView can be list. Also, I will change the background color of layout. So, I want to click on the 'background', click the 'Color' tab, and select a nice color from here. Of course, I'm selecting this color. You can choose another color if you wish. Now, that makes  the design ready. So, we can go on over to the code side. So, I want to define these three components. I will write lateinit var item : EditText lateinit var add : Button and lateinit var listView : ListView.  Now, inside the onCreate method item = findviewById(R.id.editText) add = findViewById(R.id.button) and listView = findViewById(R.id.List). So, after all that I'm going to need an array list. So, this array list will hold my items var itemList = ArrayList String. I'll add my items to the ListView from this ArrayList. Also, I'm going to need an adapter to connect ArrayList and ListView. But I will create the adapter a little bit later. So far, so good. Now, if I add items from ArrayList to the ListView using an adapter directly, that's going to cause a problem. You know why? Well, when I close the application, the list will delete. So, I need to save this list. So, I need to save this list to a file and I will actually save this list to a file in the device's memory. So then when I need this list again, I will be able to read the file from the device's memory. So, it's a little different from what we did before. What I need to do here is create a new class to save the file in the device's memory. So, I right click the project package folder, select the 'New', 'Kotlin Class/File'. I need to give a name to this class. Let's call it FileHelper. So, I will write saving quotes right in this class. Of course, we can write all of the code in the main activity without creating this class, however, see where we're going with this? It's not a very good thing to have too much code in the main activity And in addition to all that, it will always be better to make your applications according to object-oriented programming. You saw that already. So, that's why we're going to create a new class and write the necessary code here. So, first, I will create a constant for the file name. I will write val_FILENAME = "listinfo.dat". So, this is the file name that I want to save on the device's memory. I defined it at the beginning of the class because I will use this name in the code in more than one place. So, if I write this name wrong, it's going to be a problem later.

So, after that I will create a method to write data to this file. And for that I will write fun writeData(). So, this method is going to take two arguments. The first one is ArrayList. The name of the argument of this ArrayList can actually be the item. Yes. So, the type of the ArrayList is going to be string. Second one is context, so I can write context: Context. You follow? Excellent. So, I will write codes to save the list in this method.

My friends, the codes that we will write from now on are, well, important. I mean there's really no other word for that, they are important. But I'll tell you why it becomes like mega important now because we are now about to save data on the device. So, you got to listen up. I will use the FileOutputStream class. So, this is the class that we use to write data in a file. So, I create an object from this class. I write var_fos. So, fos is actually the name of the object. So, it consists of the first letters of the FileOutputStream. FileOutputStream (fos), all right. So, I'll just continue, fos : FileOutputStream = context.openFileOutput(). So, this method will create a file in the device memory and open it. This method will take two parameters, first one is the FILENAME, second one is the mode. The file name is the FILENAME constant that we defined above. The mode will be Context.MODE_PRIVATE. Now, if I select MODE_PRIVATE, I can reach this file from everywhere inside of the application that I'm writing. Other applications will not be able to reach this file, we've gone over this, but if you save data to the device's memory, you should still lock your file. Otherwise, other applications will be able to read your file. All right. Context.MODE_PRIVATE. Follow? Good. So, let's continue.

So, now I'll need to use another class and the name of this class is the ObjectOutputStream. So, for that I need to write var_oas = ObjectOutputStream. So, inside the parenthesis, I will write the fos object that we created above. These two classes are used together to write data into a file, they work as a team. So, after that I will write oas.writeObject()  as a function. And inside the parenthesis, I will write the item object which we defined as a parameter. So, with this line, the item will be written into the file. Of course, this item is an object that represents the to do item. So, when we call the writeData function in the MainActivity or anywhere for that matter, it will get the item parameter. Thus, we can send a to do item that we want to add to the list to the writeData function. And then lastly, the item will be saved in the device's memory with these codes. Okay.

So, after all that I will need to close this file. So, I just write oas.close(). So, this is important. I have created a file in the device memory. After that, I open this file, write data in this file. After that, I need to close this file because if it stays open, some problems can occur. We don't need to go into it. All right, just close it. We need to close the file, all right. So, that is the data writing method and it's ready. I will need another method though. Why is that? Well, we need a method to read this file. Yes? So, again, I'm going to write the fun keyword. Name of this method can be readData(). This method will take just one argument and it is context. Also, this function should return an ArrayList and the type of this array list will be string. So, how do you reckon this method is going to read data from the file? Well, let's take it step by step. First step, I want to create an ArrayList and that'll show the saved data in a listView again. So, I will first transfer it to this ArrayList. I will write var_itemList : ArrayList<String> After that, I will call the FileInputStream class. I will create an object from the FileInputStream class and its name is going to be fis. All right, fis : FileInputStream. Now I want you to take notice here that we're using the FileOutputStream class when we're saving the data. But we are using the FileInputStream class when reading the data. All right.

So, let's continue after the = sign. All right, context.openFileInput. Inside parenthesis, I will write the FILENAME. So, after that I will call the ObjectInputStream class, var ois = ObjectInputStream. Inside parenthesis, I'll write the fis object that I created from the FileInputStream class above. Yes, so, now we need to transfer that data that we read from the file to the ArrayList. So, I will write itemList = ois.readObject(). So, now this code will add data to the ArrayList, but my type of ArrayList is string. So, this method will read data as an object. So, I need to convert it to a string.

So, if I click on the red lamp here and select the 'Cast' option, Android Studio will do typecasting automatically. And also this method have return the itemList. So, now I can write and read items from the file using these methods. I can use these methods in the MainActivity. All right. So, I will need to specify something; when the application is first open, I need to check to see if there's a file previously saved or not. If there is saved data in the file, I'll need to take this data and write it to the ArrayList. After that, ListView can then take this data from the ArrayList. Now, I will also need to access the writeData and the readData functions that I created in the fileHelper class from within the MainActivity. So, for this, I will create an object from the fileHelper class. So, here I'm just writing var fileHelper = FileHelper(). See, so, now I gain access to the writeData and the readData functions using this FileHelper object. So, that means I can write itemList = fileHelper.readData. Then inside the parenthesis, I'll write the this keyword as the context. So then this method will read data, send it to the ArrayList if there is any data. All right. So, after that I will send this data to the ListView using the arrayAdapter. So, now we can create that ArrayAdapter. So, I'll write in here var arrayAdapter = ArrayAdapter(). ArrayAdapter will take four parameters, the first one is this, second one is the default layout for the listView. I'll write android.R.layout.simple_list_item_1. Third one is android.R.id.text1. That also happens to be the default. So, you need to write this exactly the same if you want a basic listView. Last one is the name of the ArrayList and that of course, is itemList. So, now I need to assign this adapter to the listView. So, what I need to write? listView.adapter= arrayAdapter. All right. Very good. So, now the listView is ready. If there is any saved data from before, it will be written to the listView. And also, I want to add data to the listView when I write in the EditText and click the 'Add' button. So, I need to add a ClickListener to the 'Add' button to accomplish this. Yes? So, that means I've got it right here add.setOnClickListener. And first I'll need to take the item from the EditText and assign it to a string container, var itemName : String = item.text.toString(). You're following?

So, second, I need to add this item to the ArrayList. itemList.add(itemName). Third, I want to clear the text of the EditText, item.setText(""). And that's going to clear the EditText.

Fourth, I want to write a new item to the file. If the application is closed, the data is going to be saved in the file. So, fileHelper.writeData(itemList,applicationContext). And then lastly, I'll need to notify the adapted it to get hold of these changes. So, I will write the arrayAdapter.notifyDataSetChanged(). Hang in there. The application is almost ready. Let's run the application and see how everything's working so far. Wait, just a second. It doesn't work. Why? I know there's a problem. But what is the problem? Can you find it or would you be able to find it if I gave you, I don't know, until the end of the week? No, you don't have to, because I will show you the problem. So, if you look at this error that we get, and it's a generic error. You see it all the time, probably. This is the error FileNotFoundException. So, that means when the application first opens, it can't find any file to read the data from and it throws up this error. So, what do you do? Well, we can't create a file manually.

So, that's when we use the try and catch block. So, let's go ahead and open up the FileHelper class and we can continue from there. So, what we'll do is create a try and catch block inside the readData function. Now, do you remember what try and catch really is? What you do is you define the operations that you want in the try block. So, this is what you want to do. If an error occurs, you define the necessary actions in the catch block, instead of crashing the program. So, in other words, we're going to move the cursor we wrote here to the try block and we will create an empty ArrayList in the catch block. Therefore, when the application is first opened, even if there are no files, an empty ArrayList will be created and the listView will be displayed as empty. You got it? So, let's go ahead and do it. I'll write try here and select it and press 'Enter'. Now, I'll cut the codes here that I wrote and paste them into the try block. And now we can create the catch blocks. All right. Catch in here and select it. Press 'Enter'.

Now, also I'll define the scope of the catch block with curly braces. Now you got to notice here that there's an error. Because, we got to write a parameter in parenthesis according to the error that we get. So, the name of the parameter can be e, e for error. So, I'm writing the error that we get after putting colon, namely, FileNotFoundException. Now, let's define the action to be taken when encountering an error. So here, I need to create an empty itemList. I will write itemList = ArrayList. Now, let's run the application again. All right, so you see the application works first time so the list is empty, as expected. So, I'm going to try to add some items to the list. Now, when I click the 'Add' button, items are added to listView. But of course, why are we here? The most important thing is if the data is going to be saved or not when I close the application. So, I'm going to close the application and I'll open it up again. Look at that, when the application opens again, the data all comes back. All right. So, before we celebrate, just want to complete one more thing. So, when I click on an item on the list, let's say, "Hey, I've done it. I have accomplished it. I want to now delete it." So, I need to add an item ClickListener to listView. listView.setOnItemClickListener and I'll change the I parameter to the position, and now inside the curly braces, I will create an AlertDialog message. Now you've got to remember that one. I explained the AlertDialog in one of the previous videos. So, I'll write var alert = AlertDialog.Builder(this). All right. So, after that, I'll just give a title to the AlertDialog, alert.setTitle("Delete"). And next I can define the question. alert.setMessage, message will be, "Do you want to delete this item from the list?"

And then  I will write alert.setCancelable(false). And what that means is if the user clicks somewhere on the screen, the AlertDialog will not close. Got to answer the question. Are you sure? So, alert.setNegativeButton and the name of the negative button will be "No". So, after the comma, I press the 'Control' and 'Space' keys at the same time and select the 'OnClickListener' option. If the user clicks 'No', I will write here what will happen. dialogInterface.cancel(). So, the user clicks 'No', the alert dialog will close. After that, I'll need to define a positive button and add a ClickListener to that button as well. alert dialog .setPositiveButton("Yes" and again press the 'Control', 'Space', and select 'OnClickListener'. So, if the user clicks 'Yes', I will write here what will happen. If the user clicks 'Yes', first the item that the user clicked on will be deleted from the ArrayList. So, for this, I got to write the itemList.removeAt function. And now inside the parenthesis, I'll write the index number of the item that the user's clicked on, which is the (position) parameter here. This will take the position user clicked and delete the item from the ArrayList at that very position. All right. So, second the list view is going to need to be renewed, so we can do that by notifying the adapter. So, I'll just write in here arrayAdapter.notifyDataSetChanged().

All right. And thirdly, I will need to write this new ArrayList to the file, because of course, if the application is closed, we don't want to lose data. So, fileHelper.writeData. The first parameter will be the itemList, the second parameter will be the applicationContext. And then lastly, we'll need to create and show the alertDialog. So, I'll write alert.create().show(). All right. So, everything's got to be ready now. All right. Let's try it out. We can run the application. It looks like the application is working so far. So, when I click on an item on the list, shows me the AlertDialog. Do you want to delete this item from the list? Let me click 'No' and the dialog closes. Click on the item again. And when I click 'Yes', boom there it goes. It deletes the item. Now, let's check if it's going to save the last version of the list or not. So, then close the application, open it up again, and hey what do you know? There's the save list. It brings it back. So, cool. The application is ready. Now before we finish out this video, I do want to change the logo of the application. I mentioned that earlier and thanks for not let me forget it. So, what do I need?

I'll need a picture for this. Actually, prepared one. So, I just want to copy this picture, paste it under the drawable folder. So, the picture is now in the project. After that, I can open the manifest file. So, it's in the manifest file. You see there are two code lines? The android:icon and the android:round icon. So, I need to delete this and write "drawable/todolist", because the name of the image is todolist. That's all. And also, I should write this path to the android:roundIcon as well. So, now the logo is ready. Want to run the application again. And there you can see that the logo is added. Cool. So, of course you can improve on this project, you can spend some time and really add some great functions in here. Just go all out. Make it all extra. Now, you can change the design, you might want to change the design, you can support multiple languages in the project. You can even support multiple screen sizes in the project. All of that is now up to you. All right. Play around with it. Make it everything you want it to be. All right. So, we've now finished our first project for this video. Well done. Congratulations and all that. We do need to still learn how to create an APK file using this project and then publish that APK file on Google Play. We're going to do that in, well, a little bit later in the upcoming videos. So, I'll see you then.


About the Author
Learning Paths

Mehmet graduated from the Electrical & Electronics Engineering Department of the Turkish Military Academy in 2014 and then worked in the Turkish Armed Forces for four years. Later, he decided to become an instructor to share what he knew about programming with his students. He’s currently an Android instructor, is married, and has a daughter.

Covered Topics