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)
}