Android & Kotlin experience cheat sheet

Android

Store secrets

Go to gradle.properties and save it there as key/value pairs. Exclude this file from GIT. This make it harder for others to read your secrets from your repository or using the APK file.

We could use Android’s ProGuard to make this more secure. This doesn’t provide 100% security. The best way is to keep your keys outside the project. Store them in a backend server and retrieve them after authentication. Checkout this article and this one for more information on storing secrets in Android.

MY_KEY = "1029831283712090989087"

Open the app level build.gradle file.

android {
	defaultConfig {
		buildConfigField("String", "API_KEY", MY_KEY)
	}
	
	buildTypes {
		release {
			// this deletes unused classes and files from the APK
			minifyEnabled true
			shrinkResources true
		}
	}
}

RecyclerView creation problem

I got the following exception when implementing a new RecyclerView.

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean androidx.recyclerview.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null object reference

Check the RecyclerView does not contain any child elements inside it.

RecyclerView only shows 1 child

Check the attribute layout_height is set to wrap_content and not match_parent.


Collections

Get first item of possibly empty collection

fun getFirstItem() {
    val emails = emptyList<String>()
    val mainEmail = emails.firstOrNull() ?: ""
}

Filter a list

fun filterPositives() {
  val list = listOf(-2, -1, 0, 1, 2)
  val positives = list.filter(x -> x > 0)
}

Mutable vs Inmutable collections

Kotlin’s List from the standard library is read-only. This means if we use collections from Java Libraries such as Spring Data / JPA, the List we are going to get back is not the same as a Kotlin List but a MutableIterable<> interface.

// how to mock and inject a Java 'List' in a Kotlin test
val courses = mutableListOf<Course>()
every { dao.findAll() } returns courses

Initialization / OOP

Initialize a lazy property

val p: String by lazy { "compute the String here" }

Consume a nullable Boolean

val b: Boolean? = ...
if(b == true) {
} else {
  // b is false OR null
}

Create a POJO (Plain Old Java Object)

Annotating a class with data provides this class with getters (and setters for vars) as also .toString(), equals(), copy() etc.

data class Person(val name: String, var age: Int)

Bean with automatically given ID

Example of a bean with an automatically given ID by Hibernate, primary and secondary constructors

@Entity
@Table(name = "course")
class Course(
        @Id
        @GeneratedValue(
        strategy = GenerationType.IDENTITY)
        val id: Long? = null,
        var username: String,
        var description: String) {

    constructor() :
            this(username = "",
            description = "")

    constructor(username: String,
                description: String) :
            this(null,
            username = username,
            description = description)
}

Validate user’s input data

Check the following class and values.

if(!Patterns.EMAIL_ADDRESS.matcher(inputEmail).matches()) {
	// show error
}

Flow Structures

Execute if not null or else

fun executeIfNotNull(str: String?) {
    str?.let {
        println("is not null!")
    }
}

fun ifNotNullElse() {
    val files = File("test").listFiles()
    println(files?.size ?: "empty")
}

Testing

It’s possible to use the same libraries and dependencies as with Java to transition slowly into Kotlin’s style. It uses JUnit 5. Use MockK instead of Mockito.

Kotlin has it’s own testing dependency to add to the pom.

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-test</artifactId>
    <version>check_last_version</version>
    <scope>test</scope>
</dependency>

Test template

@ExtendWith(MockKExtension::class)
internal class RestResourceTest {

  @MockK
  lateinit var service: Service

  @InjectMockKs
  lateinit var resource: Resource

  @Test
  internal fun testXXX() {
    // Given

    // When  

    // Then  

  }

}

Mocking

Same as BDDMockito.given(personDao.findOne(id)).willReturn(person)

val id = 123L
val person = Person()  
every { personDao.findOne(id) } returns person

Verify method

Same as BDDMockito.verify(personDao).findOne(id)

verify { personDao.findOne(id) }

Assert Exception

This needs the artifact kotlin-test at the POM.

assertFailsWith<Exception>("message") {
  this.restResource.getCourse(id)
}

Reference(s)

https://kotlinlang.org/docs/reference/idioms.html