Open menu with table of contents Android Assignment 02
Logo of Stuttgart Media University for light theme Logo of Stuttgart Media University for dark theme
Android Development

Android Assignment 02

Introduction to LazyColumn

Stuttgart Media University

Please conduct the following tasks alone. For implementation details you can refer to the lecture slides or the Android developer website. Please do not hesitate to ask me or the tutor if you have any questions.

1 Tasks

  • Copy the starter project assignmentCode/assignment2 from the course repository into the assignment2 folder of your Git repository and open it in Android Studio. The starter is the result of assignment 1 without the counter, plus the data model and two stubbed composables.
  • Implement MovieList: a LazyColumn that shows one MovieItem per movie of the list.
  • Implement MovieItem: a Column with three Texts (title, year, actor) and the test tag movieItem.
  • When the user clicks on an item, the movie is removed from the list.
  • Run the UI test to validate your implementation.

2 The starter project

app/src/main/java/de/hdmstuttgart/movietracker/
├── MainActivity.kt          sets the content, contains MovieList() and MovieItem() with TODOs
├── model/Movie.kt           data class Movie(title, year, actor)
└── ui/theme/                Material 3 theme generated by Android Studio
app/src/androidTest/.../Assignment2Test.kt   the UI test

The data model:

data class Movie(
    val title: String,
    val year: String,
    val actor: String
)

MovieList already holds the movies in a mutableStateListOf<Movie>(). In contrast to a normal MutableList, Compose observes this list and recomposes the LazyColumn automatically when an item is added or removed.

3 Movie item

Every item shows title, year and actor and is separated from the next one by a HorizontalDivider:

center

3.1 Hint

  • LazyColumn { items(items = movieList) { movie -> MovieItem(...) } } creates the items lazily, i.e. only the visible ones are composed.
  • Modifier.testTag("movieItem") marks the item for the test, Modifier.clickable { ... } makes it clickable. The order of modifiers matters.
  • MovieItem gets the click handler as parameter (onMovieClick: (Movie) -> Unit). The removal itself happens in MovieList, which owns the list: movieList.remove(movie).
  • See the lecture "Android Lists".

4 Movie data

The starter contains this data, do not change it (the test checks the titles):

title year actor
Dr. No 1962 Sean Connery
From Russia with Love 1963 Sean Connery
Goldfinger 1964 Sean Connery
Thunderball 1965 Sean Connery
You Only Live Twice 1967 Sean Connery

5 UI test

The test is part of the starter (app/src/androidTest/java/de/hdmstuttgart/movietracker/Assignment2Test.kt). It checks the order of the items and that clicking the first item removes it:

package de.hdmstuttgart.movietracker

import androidx.compose.ui.test.assertTextContains
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onAllNodesWithTag
import androidx.compose.ui.test.performClick
import org.junit.Rule
import org.junit.Test

class Assignment2Test {

    @get:Rule
    val composeTestRule = createAndroidComposeRule<MainActivity>()

    @Test
    fun myTest() {
        composeTestRule.onAllNodesWithTag("movieItem")[0].assertTextContains("Dr. No")
        composeTestRule.onAllNodesWithTag("movieItem")[1].assertTextContains("From Russia with Love")
        composeTestRule.onAllNodesWithTag("movieItem")[2].assertTextContains("Goldfinger")
        composeTestRule.onAllNodesWithTag("movieItem")[3].assertTextContains("Thunderball")
        composeTestRule.onAllNodesWithTag("movieItem")[4].assertTextContains("You Only Live Twice")
        composeTestRule.onAllNodesWithTag("movieItem")[0].performClick()
        composeTestRule.onAllNodesWithTag("movieItem")[0].assertTextContains("From Russia with Love")
        composeTestRule.onAllNodesWithTag("movieItem")[0].performClick()
        composeTestRule.onAllNodesWithTag("movieItem")[0].assertTextContains("Goldfinger")
    }
}

Submission

  • Push the project to the assignment2 folder of your Git repository (assignment2/app/src/main/...).
  • Check your .gitignore: no build/, .gradle/, .idea/ or local.properties.
  • For grading, your Assignment2Test.kt is replaced by the reference version and executed on a fresh emulator.