{"id":23701195,"url":"https://github.com/gitfrandu4/android-introduction-activities-kotlin","last_synced_at":"2025-08-25T00:34:19.788Z","repository":{"id":211625148,"uuid":"560646132","full_name":"gitfrandu4/android-introduction-activities-kotlin","owner":"gitfrandu4","description":"This is a simple example of how to use Activities in Android with Kotlin.","archived":false,"fork":false,"pushed_at":"2022-11-02T00:24:39.000Z","size":151,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-22T21:14:23.352Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gitfrandu4.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-11-02T00:23:01.000Z","updated_at":"2022-11-02T00:24:44.000Z","dependencies_parsed_at":"2023-12-09T19:52:44.060Z","dependency_job_id":null,"html_url":"https://github.com/gitfrandu4/android-introduction-activities-kotlin","commit_stats":null,"previous_names":["gitfrandu4/android-introduction-activities-kotlin"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gitfrandu4/android-introduction-activities-kotlin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gitfrandu4%2Fandroid-introduction-activities-kotlin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gitfrandu4%2Fandroid-introduction-activities-kotlin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gitfrandu4%2Fandroid-introduction-activities-kotlin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gitfrandu4%2Fandroid-introduction-activities-kotlin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gitfrandu4","download_url":"https://codeload.github.com/gitfrandu4/android-introduction-activities-kotlin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gitfrandu4%2Fandroid-introduction-activities-kotlin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271984371,"owners_count":24853814,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-24T02:00:11.135Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-30T09:32:35.808Z","updated_at":"2025-08-25T00:34:19.719Z","avatar_url":"https://github.com/gitfrandu4.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introduction to Android Activities with Kotlin\n\nThis is a simple example of how to use Activities in Android with Kotlin.\n\nTutorial: https://www.kodeco.com/2705552-introduction-to-android-activities-with-kotlin\n\n* Project: to-do list app named **Forget Me Not**.\n\nActivities are where all the action happens, because they are screens that allow the user to\ninteract with your app.\n\n## Activity Lifecycle\n\n![Activity Lifecycle](README_images/activity_lifecycle_pyramid.png)\n\nFollowing the diagram above, you can picture the lifecycle in action as it courses through your\ncode. Take a closer look at each of the callbacks:\n\n* **onCreate()**: Called by the OS when the activity is first created. This is where you initialize\n  any UI elements or data objects. You also have the savedInstanceState of the activity that\n  contains its previously saved state, and you can use it to recreate that state.\n* **onStart()**: Just before presenting the user with an activity, this method is called. It’s\n  always followed by onResume(). In here, you generally should start UI animations, audio based\n  content or anything else that requires the activity’s contents to be on screen.\n* **onResume()**: As an activity enters the foreground, this method is called. Here you have a good\n  place to restart animations, update UI elements, restart camera previews, resume audio/video\n  playback or initialize any components that you release during onPause().\n* **onPause()**: This method is called before sliding into the background. Here you should stop any\n  visuals or audio associated with the activity such as UI animations, music playback or the camera.\n  This method is followed by onResume() if the activity returns to the foreground or by onStop() if\n  it becomes hidden.\n* **onStop()**: This method is called right after onPause(), when the activity is no longer visible\n  to the user, and it’s a good place to save data that you want to commit to the disk. It’s followed\n  by either onRestart(), if this activity is coming back to the foreground, or onDestroy() if it’s\n  being released from memory.\n* **onRestart()**: Called after stopping an activity, but just before starting it again. It’s always\n  followed by onStart().\n* **onDestroy()**: This is the final callback you’ll receive from the OS before the activity is\n  destroyed. You can trigger an activity’s desctruction by calling finish(), or it can be triggered\n  by the system when the system needs to recoup memory. If your activity includes any background\n  threads or other long-running resources, destruction could lead to a memory leak if they’re not\n  released, so you need to remember to stop these processes here as well.\n\n\u003e Note: You do not call any of the above callback methods directly in your own code (other than superclass invocations) — you only override them as needed in your activity subclasses. They are called by the OS when a user opens, hides or exits the activity.\n\n## Configuring an Activity\n\n```kotlin\nclass MainActivity : AppCompatActivity() {\n\n    // 1. You initialize the activity’s properties, which include an empty mutable list of tasks and an\n    // adapter initialized using by lazy.\n    private val taskList = mutableListOf\u003cString\u003e()\n    private val adapter by lazy { makeAdapter(taskList) }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        // 2. You call onCreate() on the superclass — remember that this is (usually) the first thing\n        // you should do in a callback method. There are some advanced cases in which you may call\n        // code prior to calling the superclass.\n        super.onCreate(savedInstanceState)\n        // 3. You set the content view of your activity with the corresponding layout file resource.\n        setContentView(R.layout.activity_main)\n\n        // 4. Here you set up the adapter for taskListView. The reference to taskListView is initialized\n        // using Kotlin Android Extensions. This replaces findViewById() calls and the need for other\n        // view-binding libraries.\n        taskListView.adapter = adapter\n\n        // 5. You add an empty OnItemClickListener() to the ListView to capture the user’s taps on\n        // individual list entries. The listener is a Kotlin lambda.\n        taskListView.onItemClickListener =\n            AdapterView.OnItemClickListener { parent, view, position, id -\u003e\n                // stuffs...\n            }\n    }\n\n    // 6. An empty on-click method for the “ADD A TASK” button, designated by the activity_main.xml layout.\n    fun addTaskClicked(view: View) {\n\n    }\n\n    // 7. A private function that initializes the adapter for the list view. Here you are using\n    // the Kotlin = syntax for a single-expression function.\n    private fun makeAdapter(list: List\u003cString\u003e): ArrayAdapter\u003cString\u003e =\n        ArrayAdapter(this, android.R.layout.simple_list_item_1, list)\n}\n```\n\n## Starting an Activity\n\nAnd add the following implementation for addTaskClicked():\n\n```kotlin\nfun addTaskClicked(view: View) {\n    // Create an intent to start the AddTaskActivity\n    val intent = Intent(this, TaskDescriptionActivity::class.java)\n    // Start the activity, and pass in the request code\n    startActivityForResult(intent, ADD_TASK_REQUEST)\n}\n```\n\nYou can start an activity with either `startActivity()` or `startActivityForResult()`. They are\nsimilar except that `startActivityForResult()` will result in `onActivityResult()` being called once\nthe\n`TaskDescriptionActivity` finishes.\n\n\u003e Note: Intents are used to start activities and pass data between them. For more information, check\n\u003e out the Android: Intents Tutorial: https://www.kodeco.com/4700198-android-intents-tutorial-with-kotlin\n\n## Creating an Activity\n\n[...] Android Studio will automatically generate the corresponding resources needed to create the\nactivity. These are:\n\n* **Class**: The class file is named `TaskDescriptionActivity.kt`. This is where you implement the\n  activity’s behavior. This class must subclass the Activity class or an existing subclass of it,\n  such as AppCompatActivity.\n\n* **Layout**: The layout file is located under res/layout/ and named activity_task_description.xml.\n  It defines the placement of different UI elements on the screen when the activity is created.\n\nIn addition to this, you will see a new addition to your app’s `AndroidManifest.xml` file:\n\n```xml\n\n\u003cactivity android:name=\".TaskDescriptionActivity\"\u003e\u003c/activity\u003e\n```\n\nThe `activity` element declares the activity. Android apps have a strong sense of order, so all\navailable activities must be declared in the manifest to ensure the app only has control of\nactivities declared here. You don’t want your app to accidentally use the wrong activity, or even\nworse, have it use activities that are used by other apps without explicit permission.\n\nThere are several attributes that you can include in this element to define properties for the\nactivity, such as a label or icon, or a theme to style the activity’s UI.\n\n`android:name` is the only required attribute. It specifies the activity’s class name relative to\nthe app package (hence the period at the beginning).\n\nNow build and run the app. When you tap on ADD A TASK, you’re presented with your newly generated\nactivity!\n\n![add_a_task activity](README_images/add_a_task.png)\n\nIn your newly generated TaskDescriptionActivity, paste the following into your class file,\noverwriting anything else except the class declaration and its brackets.\n\n```kotlin\n// 1. Used the Kotlin companion object for the class to define attributes common across the class, \n// similar to static members in Java.\ncompanion object {\n    val EXTRA_TASK_DESCRIPTION = \"task\"\n}\n\n// 2. Overriden the onCreate() lifecycle method to set the content view for the activity from the layout file.\noverride fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n    setContentView(R.layout.activity_task_description)\n}\n\n// 3. Added an empty click handler that will be used to finish the activity.\nfun doneClicked(view: View) {\n\n}\n```\n\n## Stopping an Activity\n\nJust as important as starting an activity with all the right methods is properly stopping it.\n\nAdd the following to `doneClicked()`, which is called when the Done button is tapped in this\nactivity:\n\n```kotlin\nfun doneClicked(view: View) {\n// 1. You retrieve the task description from the descriptionText EditText, where Kotlin Android Extensions \n// has again been used to get references to view fields.\n    val taskDescription = descriptionText.text.toString()\n\n    if (!taskDescription.isEmpty()) {\n        // 2. You create a result Intent to pass back to MainActivity if the task description retrieved \n        // in step one is not empty. Then you bundle the task description with the intent and set the \n        // activity result to RESULT_OK, indicating that the user successfully entered a task.\n        val result = Intent()\n        result.putExtra(EXTRA_TASK_DESCRIPTION, taskDescription)\n        setResult(Activity.RESULT_OK, result)\n    } else {\n        // 3. If the user has not entered a task description, you set the activity result to RESULT_CANCELED.\n        setResult(Activity.RESULT_CANCELED)\n    }\n\n// 4. Here you close the activity.\n    finish()\n}\n```\n\nOnce you call `finish()` in step four, the callback `onActivityResult()` will be called\nin `MainActivity` — in turn, you need to add the task to the to-do list.\n\nAdd the following method to MainActivity.kt, right after `onCreate()`:\n\n````kotlin\noverride fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n    // 1. You check the requestCode to ensure the activity result is indeed for your add task request \n    // you started with TaskDescriptionActivity.\n    if (requestCode == ADD_TASK_REQUEST) {\n        // 2. You make sure the resultCode is RESULT_OK — the standard activity result for a successful \n        // operation.\n        if (resultCode == Activity.RESULT_OK) {\n            // 3. Here you extract the task description from the result intent and, after a null check with \n            // the let function, add it to your list.\n            val task = data?.getStringExtra(TaskDescriptionActivity.EXTRA_TASK_DESCRIPTION)\n            task?.let {\n                taskList.add(task)\n                // 4. Finally, you call notifyDataSetChanged() on your list adapter. In turn, it notifies the \n                // ListView about changes in your data model so it can trigger a refresh of its view.\n                adapter.notifyDataSetChanged()\n            }\n        }\n    }\n}\n````\n\nBuild and run the project to see it in action.\n\n## Persisting State\n\n### Persisting Data Between Launches\n\nOpen MainActivity.kt, and add the following properties to the top of the class:\n\n```kotlin\nprivate val PREFS_TASKS = \"prefs_tasks\"\nprivate val KEY_TASKS_LIST = \"tasks_list\"\n```\n\nAnd add the following underneath the rest of your activity lifecycle methods.\n\n```kotlin\noverride fun onStop() {\n    super.onStop()\n\n    // Save all data which you want to persist.\n    val savedList = StringBuilder()\n    for (task in taskList) {\n        savedList.append(task)\n        savedList.append(\",\")\n    }\n\n    getSharedPreferences(PREFS_TASKS, Context.MODE_PRIVATE).edit()\n        .putString(KEY_TASKS_LIST, savedList.toString()).apply()\n}\n```\n\nHere you build a comma separated string with all the task descriptions in your list, and then you\nsave the string\nto [SharedPreferences](https://developer.android.com/reference/kotlin/android/content/SharedPreferences)\nin the `onStop()` callback. As mentioned earlier, **`onStop()` is a good place to save data that you\nwant to persist across app uses**.\n\nNext add the following to `onCreate()` below the existing initialization code:\n\n```kotlin\nval savedList =\n    getSharedPreferences(PREFS_TASKS, Context.MODE_PRIVATE).getString(KEY_TASKS_LIST, null)\nif (savedList != null) {\n    val items = savedList.split(\",\".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()\n    taskList.addAll(items)\n}\n```\n\nHere you read the saved list from the SharedPreferences and initialize taskList by converting the \nretrieved comma separated string to a typed array.\n\n\u003e Note: You used SharedPreferences since you were only saving primitive data types. For more complex\n\u003e data you can use a variety of storage options available on Android.\n\n### Configuration Changes\n\nYou need the ability to delete entries from Forget Me Not.\n\nStill in MainActivity.kt, at the bottom of the class add:\n\n```kotlin\nprivate fun taskSelected(position: Int) {\n  // 1. create an AlertDialog.Builder which facilitates the creation of an AlertDialog.\n  AlertDialog.Builder(this)\n    // 2. set the alert dialog title.\n    .setTitle(R.string.alert_title)\n    // 3. set the alert dialog message to be the description of the selected task. Then you also implement \n    // the PositiveButton to remove the item from the list and refresh it, and the NegativeButton to dismiss the dialog.\n    .setMessage(taskList[position])\n    .setPositiveButton(R.string.delete, { _, _ -\u003e\n      taskList.removeAt(position)\n      adapter.notifyDataSetChanged()\n    })\n    .setNegativeButton(R.string.cancel, {\n      dialog, _ -\u003e dialog.cancel()\n    })\n    // 4. create the alert dialog.\n    .create()\n    // 5. display the alert dialog to the user.\n    .show()\n}\n```\n\nUpdate the `OnItemClickListener` of the taskListView in `onCreate():\n\n```kotlin\ntaskListView.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -\u003e\n  taskSelected(position)\n}\n```\n\n### Handling Configuration Changes\n\nConfiguration changes, such as rotation, keyboard visibility and so on, cause an activity to \nshut down and restart. You can find the full list of system events that cause an activity to be recreated \n[here](https://developer.android.com/guide/topics/manifest/activity-element.html#config).\n\nThere are a couple of ways you can handle a configuration change.\n\nOne way is as follows. In AndroidManifest.xml, find the start tag:\n\n```xml\n\u003cactivity android:name=\".MainActivity\"\u003e\n```\n\nAnd change it to:\n\n```xml\n\u003cactivity android:name=\".MainActivity\" android:configChanges=\"orientation|screenSize\"\u003e\n```\n\nHere, you declare that your `MainActivity` will handle any configuration changes that arise from a \nchange in orientation or screen size. This simple line prevents a restart of your activity by the \nsystem, and it passes the work to `MainActivity`.\n\nYou can then handle these configuration changes by implementing `onConfigurationChanged()`. In \n`MainActivity.kt`, add the following method after `onStop()`:\n\n```kotlin\noverride fun onConfigurationChanged(newConfig: Configuration?) {\n  super.onConfigurationChanged(newConfig)\n}\n```\n\nHere you’re just calling the superclass’s `onConfigurationChanged()` method since you’re not updating \nor resetting any elements based on screen rotation or size.\n\n`onConfigurationChanged()` is passed a Configuration object that contains the updated device configuration.\n\nBy reading fields in this newConfig, you can determine the new configuration and make appropriate \nchanges to update the resources used in your interface.\n\n# Resources\n\nIntroduction to Android Activities with Kotlinby @stevenpsmith123 https://www.kodeco.com/2705552-introduction-to-android-activities-with-kotlin a través de @kodecodev \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgitfrandu4%2Fandroid-introduction-activities-kotlin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgitfrandu4%2Fandroid-introduction-activities-kotlin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgitfrandu4%2Fandroid-introduction-activities-kotlin/lists"}