Skip to content

Instantly share code, notes, and snippets.

@muthuraj57
Last active April 25, 2019 10:17
Show Gist options
  • Save muthuraj57/446128b34eba099425574417cb6c37e7 to your computer and use it in GitHub Desktop.
Save muthuraj57/446128b34eba099425574417cb6c37e7 to your computer and use it in GitHub Desktop.
Kotlin Basics
package com.muthuraj.kotlinBasics.kotlinbasics;
import android.graphics.Color;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Muthuraj on 2019-03-13.
* <p>
*/
public class JavaClass {
private String someField = "test";
public static class Dog {
String name;
String owner;
String anotherField = "test";
public Dog(){
}
public Dog(String name, String owner) {
this.name = name;
this.owner = owner;
}
final void print(){
new DogKt.InnerDog();
System.out.println("Name: " + name + ", Owner: " + owner);
System.out.println(this);
DogKt dogKt = new DogKt("name", "owner");
dogKt.getName();
}
void setDetailsInterface(DetailsInterface detailsInterface){
detailsInterface.getDetails();
}
@NonNull
@Override
public String toString() {
return "Name: " + name + ", Owner: " + owner;
}
String getName(){
return name;
}
String getOwner(){
return owner;
}
// public void setName(String name) {
// this.name = name;
// }
public void setOwner(String owner) {
this.owner = owner;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Dog dog = (Dog) o;
if (name != null ? !name.equals(dog.name) : dog.name != null) return false;
return owner != null ? owner.equals(dog.owner) : dog.owner == null;
}
}
// <========================== Function =========================>
int add(int a, int b){
return a + b;
}
void addAndPrint(int a, int b){
System.out.println(a+b);
}
// <========================== Late init =========================>
String variable = "";
int a = 10;
String anotherVariable;
void initializeVariable(){
anotherVariable = "value goes here";
}
//Calling access() before initializeVariable will crash with
//NullPointerException exception
void access(){
System.out.println(anotherVariable);
}
// <========================== Object creation =========================>
Dog dogInstance = new Dog("Tiger", "Muthu");
void test(){
dogInstance.print();
}
// <========================== Val, Var =========================>
final String logTag = "Java";
String logTagAnother = "Java";
void test1(){
logTag = "Cannot change"; //Compile time error
logTagAnother = "Can change this";
}
// <========================== Smart casting =========================>
void test2(){
String value = null;
int a;
if (value == null) {
System.out.println(value.length()); // Run time error (crash)
a = 1;
} else{
System.out.println(value.length());
a = 2;
}
}
// <========================== Named Arguments =========================>
void test5(){
Dog dog = new Dog("Tiger", "Muthu");
}
// <========================== Default Arguments =========================>
//Default arguments can be achieved in Java using method overriding
String formatString(String str, boolean upperCase, boolean printLog){
if(upperCase){
if(printLog){
String result = str.toUpperCase();
Log.d("formatString", result);
return result;
} else{
return str.toUpperCase();
}
} else{
if(printLog){
Log.d("formatString", str);
}
return str;
}
}
String formatString(String str){
return formatString(str, false, false);
}
void test6(){
formatString("test", false, true);
formatString("test");
}
// <========================== Static =========================>
static String NAME = "StaticExample";
static final int AGE = 20;
void test3(){
NAME = "Some other value";
AGE = 21; //Compile time error
}
static void staticMethod(){
}
static class Test{
}
// <========================== Loops =========================>
void test7(){
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
for (String item : list) {
System.out.println("item: "+item);
}
}
// <========================== Inheritance, Object, Override =========================>
class BullDog extends Dog implements SomeInterface{
public BullDog(String name, String owner) {
super(name, owner);
//network call
}
public BullDog(String name) {
super(name, "test");
//network call
}
@Override
public void method() {
}
void printBullDog(){
System.out.println("BullDog name: " + name + ", owner: " + owner);
}
}
interface SomeInterface{
void method();
}
// <========================== init block =========================>
// <========================== Casting, Type check =========================>
void test4(){
Dog dog = new Dog("name goes here", "owner goes here");
((BullDog) dog).printBullDog();
if (dog instanceof BullDog) {
((BullDog) dog).printBullDog();
} else{
dog.print();
}
}
void test5(Object obj){
if (obj instanceof String) {
((String) obj).length();
}
((String) obj).length();
}
// <========================== Switch vs when =========================>
void test6(Object obj){
String a = "2";
String b = "4";
boolean sss;
if(a == b){
sss = true;
} else{
sss = false;
}
String res = "";
if(obj == 1 || obj == 2){
res = "One";
} else if(obj == "Testing"){
res = "Testing String";
} else if(obj instanceof Long){
res = "Long";
} else if(!(obj instanceof Double)){
res = "Not a Double";
}
switch (((int) obj)){
case 1:
res = "one";
break;
case 2:
res = "two";
break;
default:
res = "no value";
break;
}
}
// <========================== Singleton =========================>
//Refer SingletonExample.java
// <========================== Lambda =========================>
void lambdaTes(){
TextView textView = new TextView(this);
//Java classic Anonymous inner class
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//showToast
}
});
//Java lambda
textView.setOnClickListener(v -> {
//showToast
});
Dog dog = new Dog();
dog.setDetailsInterface(new DetailsInterface() {
@Override
public void getDetails() {
//Do something
}
});
}
interface DetailsInterface {
void getDetails();
}
// <========================== Collections =========================>
private List<String> list = new ArrayList<>();
void test8(){
list.add("apple");
list.add("orange");
}
// <========================== Inner class =========================>
/*
* 1. Normal inner classes can access outer class members
* 2. Normal inner classes can only be created with outer class instance
* 3. Static inner classes can't access outer class members
* 4. Static inner classes can be created directly without any instance
* */
// <========================== Equality =========================>
// == checks reference
// .equals() checks value
void testEquality(){
String first = null;//"Test";
String second = "Test";
boolean firstResult = first == second; //returns true
String stringFromSomeCalculation = "OneTestOne".substring(3, 7);
boolean secondResult = stringFromSomeCalculation == second; // returs false
first.equals(second); // will crash since first is null
}
// <========================== Exceptions =========================>
//Checked exceptions should be handled with try catch or
//throws should be added in Class/method signature
JSONObject toJson(String jsonString) throws JSONException {
return new JSONObject(jsonString);
}
void exceptionTest(){
String string = " \"data\" : { \"key\" : \"value\" }";
//Compiler error since exception is handled
JSONObject jsonObj = toJson(string);
try {
JSONObject jsonObject = toJson(string); // works fine
} catch (JSONException e) {
e.printStackTrace();
}
}
// <========================== Closable =========================>
void testClosable(){
//Classic Java way
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(new File("test.txt"));
//do something with fileInputStream
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//Try with resources
try (FileInputStream stream = new FileInputStream(new File("test.txt"))) {
//do something with stream
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// <========================== Extension functions =========================>
JSONObject toJson(String jsonString) throws JSONException {
return new JSONObject(jsonString);
}
int toColor(String colorValue){
return Color.parseColor(colorValue);
}
void extenstionFuncTest(){
String string = " \"data\" : { \"key\" : \"value\" }";
String value = "#ff3431";
JSONObject json = toJson(string);
int color = toColor(value);
}
// <========================== Collections utils =========================>
void collectionsUtilTest(){
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
List<String> result = new ArrayList<>();
for (Integer value :list){
if (value > 2) {
result.add(value.toString());
}
}
}
// <========================== Common Extensions - Java equivalent=========================>
private Dog dog = null;
void commonExtensionsTest(){
dog = new Dog();
dog.name = "something";
dog.owner = "owner";
if (dog != null) {
String name = dog.name;
if (name != null && !name.isEmpty()) {
someOtherFunction(name);
}
}
}
void someOtherFunction(String name){
//Do something
}
// <========================== Data class =========================>
class Name{
private String firstName;
private String lastName;
public Name(String firstName, String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Name name = (Name) o;
if (firstName != null ? !firstName.equals(name.firstName) : name.firstName != null) return false;
return lastName != null ? lastName.equals(name.lastName) : name.lastName == null;
}
@Override
public int hashCode() {
int result = firstName != null ? firstName.hashCode() : 0;
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Name{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
}
void dataClassTest(){
Name name = new Name("Muthu", "Raj");
Name anotherName = new Name("Muthu", "Raj");
name.equals(anotherName);
System.out.println(name);
}
// <========================== Enums =========================>
enum LoginStateEnum{
LOGGED_IN,
LOGGING_IN,
LOGGED_OUT
}
void enumTest(){
LoginStateEnum loggedInState = getLoggedInEnumState();
switch (loggedInState) {
case LOGGED_IN:
System.out.println("Logged in ");
//Update UI to reflect login state
break;
case LOGGED_OUT:
System.out.println("Logged out");
//Update UI to reflect logged state
break;
}
}
LoginStateEnum getLoggedInEnumState(){
//check and return current login state
return LoginStateEnum.LOGGED_IN;
}
String enumCheckAllBranches(){
LoginStateEnum loggedInState = getLoggedInEnumState();
String state = "";
switch (loggedInState) {
case LOGGED_IN:
state = "Logged in";
break;
case LOGGED_OUT:
state = "Logged out";
break;
}
return state;
}
// <========================== Sealed Class =========================>
class LoginState{
}
class LoggedIn extends LoginState{
String name;
public LoggedIn(String name) {
this.name = name;
}
}
class LoggedOut extends LoginState{
}
LoginState getLoggedInState() {
if(true /*login check*/){
return new LoggedIn("Muthuraj");
} else{
return new LoggedOut();
}
}
void loginTest(){
LoginState loginState = getLoggedInState();
if(loginState instanceof LoggedIn){
String userName = ((LoggedIn) loginState).name;
//Update UI
} else if(loginState instanceof LoggedOut){
//Update UI
}
}
// <========================== Ranges =========================>
void ranges(){
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
void getViewGroupChildren(){
List<View> children = new ArrayList<>();
LinearLayout linearLayout = new LinearLayout(this);
for (int i = 0; i < linearLayout.getChildCount(); i++) {
children.add(linearLayout.getChildAt(i));
}
}
// <========================== Compile time constants =========================>
//There is no compile time constants in Java
class Constants{
public static final String URL = "https://www.google.com";
public static final String EVENT = "clicked";
}
// <========================== Multi line String =========================>
public static void main(String[] args) {
multiLineString();
}
static void multiLineString(){
String s = "This" +
"is" +
"a " +
"multi-" +
"line" +
"string";
System.out.println(s);
}
/* $Id$ */
package com.muthuraj.kotlinBasics.kotlinbasics
import android.graphics.Color
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.muthuraj.kotlinBasics.kotlinbasics.JavaClass.*
import org.json.JSONObject
import java.io.File
import java.io.FileInputStream
import java.lang.Exception
import java.util.ArrayList
/**
* Created by Muthuraj on 2019-03-13.
*
*/
open class DogKt(var name: String, val owner: String = "test") {
open val anotherField: String = "test"
//Another way to provide constructor
// constructor(name: String = "Muthu", owner: String = "Owner") {
// this.name = name
// this.owner = owner
// }
fun print(): Int{
val s = 1
val s1 = 2
//Java style string concat
println("Name: " + name + ", Owner: " + owner)
//String interpolation
println("Name: $name, ${s+s1} Owner: $owner")
val dog = Dog(name, owner)
return 1
}
fun setDetailsInterface(detailsInterface: DetailsInterface){
detailsInterface.getDetails()
}
//Custom operator overloading
operator fun plusAssign(name: String){
this.name = name
}
class InnerDog(){
init {
// name
}
}
}
class DogKt1(private var name: String, private var owner: String){
fun print(): Int{
println("Name: " + name + ", Owner: " + owner)
return 1
}
}
// <========================== Function =========================>
//Function body and return keyword is not needed if return
// statement is single line
fun add(a: Int, b: Int): Int = a + b
//System.out.println => println
fun addAndPrint(a: Int, b: Int){
println(a+b)
}
// <========================== Late init =========================>
//Also refer MainFragment in MainActivity.kt
var variable = ""
var a = 10
lateinit var anotherVariable: String
fun initializeVariable(): Unit{
anotherVariable = "value goes here"
}
//Calling access() before initializeVariable will crash with
//UninitializedPropertyAccessException exception
fun access(){
println(anotherVariable)
}
// <========================== Object creation =========================>
var dogInstance = DogKt("Tiger", "Muthu") //no new keyword
fun test(){
dogInstance.print()
}
// <========================== Val, Var =========================>
val logTag = "Kotlin"
var logTagAnother = "Java"
fun test1(){
logTag = "Cannot change" //Compile time error
logTagAnother = "Can change this"
}
// <========================== Smart casting =========================>
fun test2(){
var value: String? = null
val dog: DogKt? = null
val lenght = value?.length ?: 0
if (value == null) {
println(value.length) //Compile time error
} else{
value = "Assign some value"
println(value.length) //Smart casted from String? to String
}
}
/**
* Recap
*
* class
* fun
* val
* var
* void vs Unit
* class instance creation (no new keyword)
* null, not null (?.)
*
* a ?: "abv"
* null safety ?,?:
* if..else (no ternary)
* smart casting
*/
// <========================== Named Arguments =========================>
fun test5() {
val dog = Dog("Muthu", "Tiger")
//Constructor order doesn't matter if called this way
val dog1 = DogKt(owner = "Muthu",name = "Tiger")
//Function parameters order doesn't matter if called this way
named("name",age = 5, owner = "Muthu")
}
fun named(name: String, owner: String?, age: Int){
//Do something
}
// <========================== Default Arguments =========================>
fun formatString(str: String, upperCase: Boolean = false, printLog: Boolean): String {
if (upperCase) {
if (printLog) {
val result = str.toUpperCase()
Log.d("formatString", result)
return result
} else {
return str.toUpperCase()
}
} else {
if (printLog) {
Log.d("formatString", str)
}
return str
}
}
fun test6() {
//upperCase will be false here
formatString(str = "test", printLog = false)
}
// <========================== Static =========================>
class StaticHelper{
//No static keyword. Everything inside companion is static.
companion object {
private var NAME = "StaticExample"
val AGE = 20
fun staticMethod(){
}
}
fun test3(){
NAME = "Some other value"
AGE = 21 //Compile time error
}
}
// <========================== Loops =========================>
fun test7() {
val list = ArrayList<String>()
list.add("1")
list.add("2")
list.add("3")
list.add("4")
list.add("5")
for (item in list) {
println("item: $item")
}
}
// <========================== Inheritance, Any, Override =========================>
//Java Object == Kotlin Any
class BullDog(name: String, owner: String = "test"): DogKt(owner = owner, name = name), SomeInterface{
//Another way to provide constructor
// constructor(name: String, owner: String): super(name, owner)
//Called after constructor invocation
init {
//network call
}
fun printBullDog(){
println("BullDog name: $name, owner: $owner")
}
override val anotherField: String = "test1"
override fun method() {
}
}
interface SomeInterface{
fun method()
}
// <========================== init block =========================>
// <========================== Casting, Type check =========================>
fun test4(){
val dog: DogKt = DogKt("name goes here", "owner goes here")
(dog as? BullDog)?.printBullDog() ?: "something"
if (dog is BullDog) {
dog.printBullDog() //Smart casted from DogKt to BullDog
} else{
dog.print()
}
}
fun test5(obj: Any){
if (obj is String) {
obj.length
}
(obj as? String)?.length
(obj as String).length
}
/**
* Recap
*
* Named arguments
* Default arguments
* static fields and methods
* Loops
* Inheritance, override
* Any
* Init block
* Type check and type casting
*/
// <========================== Switch vs when =========================>
fun test6(obj: Any?) {
val a = "2"
val b = "4"
val sss = if (a == b) true else false
val ss: String?
when (obj) {
1,2,32,4 -> ss = "One"
"Testing" -> ss = "Testing String"
is Long -> ss = "Long"
!is Double -> ss = "Not a Double"
else -> ss = null
}
val res: String
when(obj){
1 -> {
res = "one";
}
2 ->{
res = "two"
}
else ->{
res = "no value"
}
}
}
// <========================== Singleton =========================>
//Refer SingletonExample.kt
// <========================== Lambda =========================>
fun lambdaTest(){
val textView = TextView(this)
//Kotlin lambda
textView.setOnClickListener {v->
//showToast
}
val dog = Dog();
dog.setDetailsInterface {
//Do something
}
//SAM conversion won't work with Kotlin interface.
//So anonymous inner class is the way to go here.
val dogKt = DogKt()
dogKt.setDetailsInterface(object: DetailsInterface {
override fun getDetails() {
}
})
}
interface DetailsInterface{
fun getDetails()
}
// <========================== Collections =========================>
fun test8(){
//Java style
val list = ArrayList<String>()
list.add("apple")
list.add("orange")
//Kotlin style
val immutableList: List<String> = listOf("apple","orange")
val mutableList: MutableList<String> = mutableListOf("apple","orange")
mutableList.add("")
}
/**
* Recap
*
* Switch vs when
* Singleton (object)
* Lambda, SAM conversion
* Collections (listOf, mutableListOf)
*/
// <========================== Top level declaration =========================>
//Every method, variable in this file is declared at top level
// <========================== Inner class =========================>
/*
* 1. Default inner class is Java style static inner class
* 2. Classes with `inner` keyword can access outer class member and
* can only be created with outer class instance
* */
class KotlinAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
// private val data = mutableListOf<String>()
//This is better than above line
private var data = emptyList<String>()
fun updateData(newData: List<String>){
//For val mutableList type
// data.clear()
// data.addAll(newData)
//For val list type
data = newData
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return ViewHolder(View.inflate(parent.context, R.layout.activity_main, parent))
}
override fun getItemCount(): Int {
return data.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as ViewHolder).setData(data[position])
}
}
class ViewHolder(private val item: View): RecyclerView.ViewHolder(item){
private val textView = item.findViewById<TextView>(R.id.text_view)
fun setData(data: String){
item
textView.text = data
}
}
// <========================== Lazy delegate =========================>
//Refer MainActivity.kt
/**
* Recap
*
* Top level declaration
* Inner class
* Lazy delegate, lateinit var
*/
// <========================== Equality =========================>
// == checks value
// === checks reference
internal fun testEquality() {
val first: String? = null//"Test"
val second = "Test"
val firstResult = first == second //returns true
val stringFromSomeCalculation = "OneTestOne".substring(3, 7)
stringFromSomeCalculation == second // returs true
}
// <========================== Exceptions =========================>
//No checked exceptions
fun toJson(jsonString: String): JSONObject?{
return JSONObject(jsonString)
}
//One way to handle exception (return null on exception case)
fun toJson(jsonString: String): JSONObject?{
try {
return JSONObject(jsonString)
}catch (e: Exception){
return null
}
}
fun exceptionTest(){
val string: String? = " \"data\" : { \"key\" : \"value\" }"
//No compiler error to handle exception
val json = string.toJson()
}
// <========================== Closable =========================>
//kotlin way
fun testClosable(){
val fileInputStream = FileInputStream(File("test.txt"))
fileInputStream.use {stream ->
//do something with stream
}
}
// <========================== Extension functions =========================>
//fun toJson(jsonString: String): JSONObject{
// return JSONObject(jsonString)
//}
fun String.toJson(): JSONObject {
return JSONObject(this)
}
fun View.isVisible(): Boolean{
return visibility == View.VISIBLE
}
fun String.toColor(): Int{
return Color.parseColor(this)
}
fun extensionFuncTest(){
val string = " \"data\" : { \"key\" : \"value\" }"
val value = "#ff3431"
val json = string.toJson()
val color = value.toColor()
}
// <========================== Collections utils =========================>
//Filter, map, find, any, sublist, subtract, union
fun collectionsUtilTest(){
val list = listOf(1,2,3,4,5)
val anotherList = listOf(4,5,3,2,1)
arrayOf(1,2,3)
list.filter { it > 2 }
.map { it.toString() }
}
// <========================== Common Extensions =========================>
//let, apply, takeIf
private var dog: Dog? = null
private val dogg = Dog().apply {
name = ""
owner = ""
}
fun commonExtensionsTest(){
val d = Dog()
d.name = "something"
d.owner = "owner"
dog = Dog().apply {
name = "something"
owner = "owner"
}
if (dog != null) {
if (dog!!.name != null) {
someOtherFunction(dog!!.name!!)
}
}
val name = dog?.name
someOtherFunction(dog?.name) //Error
dog?.name
?.takeIf { it.isNotEmpty() }
?.let { someOtherFunction(it) }
}
fun someOtherFunction(name: String): Int?{
//Do something
return name.length
}
// <========================== Data class =========================>
data class Name(val firstName: String, var lastName: String){
}
fun dataClassTest(){
val name = Name("Muthu", "Raj")
name.copy(lastName = "Raja")
//send name to server
}
// <========================== Enums =========================>
enum class LoginStateEnum {
LOGGED_IN,
LOGGING_IN,
LOGGED_OUT
}
fun enumTest(){
val loginState = getLoggedInEnumState()
//when produces compile errors only if when statement result is consumed.
//To do that, we create a dummy extension method named consumeWhen
//and call that with when statement.
when (loginState) {
LoginStateEnum.LOGGED_IN -> {
println("Logged in ")
//Update UI to reflect login state
"Logged in "
}
LoginStateEnum.LOGGED_OUT -> {
println("Logged out")
//Update UI to reflect logged state
"Logged out"
}
}.consumeWhen() //without this call, when won't produce error
}
fun <T> T.consumeWhen(): T{
return this
}
fun getLoggedInEnumState(): LoginStateEnum{
//check and return current login state
return LoginStateEnum.LOGGED_IN
}
fun enumCheckAllBranches(): String{
val loginState = getLoggedInEnumState()
val state: String
when (loginState) {
LoginStateEnum.LOGGED_IN -> {
state = "Logged in"
}
LoginStateEnum.LOGGED_OUT -> {
state = "Logged out"
}
}
return state
}
// <========================== Sealed class =========================>
sealed class LoginState {
class LoggedIn(val name: String) : LoginState()
class LoggedOut : LoginState()
class LoggingIn : LoginState()
}
fun getLoggedInState(): LoginState{
if(true /*login check*/){
return LoginState.LoggedIn("Muthuraj")
} else{
return LoginState.LoggedOut()
}
}
fun loginTest(){
val loginState = getLoggedInState()
when (loginState) {
is LoginState.LoggedIn -> {
val userName = loginState.name
//Update UI
}
is LoginState.LoggedOut -> {
//Update UI
}
}.consumeWhen()
}
fun <T> T.consumeWhen(): T{
return this
}
// <========================== Operator overloading =========================>
fun operators(){
val list = mutableListOf("1", "2", "3", "4")
list.get(2) //==> list[2]
list.add("5") //==> list += "5"
list.set(2, "5") //==> list[2] = "5"
list[2]
list += "5"
list[2] = "5"
var a: Int = 5
a += 4
val anotherList = listOf("5", "6")
val newList = list + anotherList
list -= anotherList //subtracts contents of anotherList from list
val map = mapOf("1" to "4", "2" to "5")
val value = map["2"]
}
// <========================== Ranges =========================>
//1. Range can be created with double dot or until keyword.
//2. Ranges can only created for primitive types
//3. All common collection utils are available for range too (ex: map, filter..)
fun ranges(){
val range = 0..10
//Prints 0 to 10 (including 10)
for (i in 0..10){
println(i)
}
//Prints 0 to 9
for (i in 0..10-1){
println(i)
}
// 0..10-1 ==> 0 until 10
val list = listOf<String>()
for (i in 0 until list.size){
println(i)
}
}
fun getViewGroupCildren(){
val linearLayout = LinearLayout(this)
val children = (0 until linearLayout.childCount)
.map { linearLayout.getChildAt(it) }
}
// <========================== set, get =========================>
// set will have `value` and `field`
// `value` will hold new value passed through set call
// `field` can be used to refer the actual member field
// get will have `field`
class Employee(name: String){
var salary: Double = 0.0
private set
get() {
//do something on getSalary call
return field
}
private val _name = name
fun updateSalary(newSalary: Double){
salary = newSalary
}
}
fun setTest(){
val employee = Employee("Name")
val sal = employee.salary //get is public, so this will work
employee.salary = 0.0 //set is private, so this will be compile error
}
// <========================== Compile time constants =========================>
//Used with const keyword
//Can be used only in top level declaration, inside object or companion object
//Primitive types and Strings only supported
class CompileExample {
companion object {
const val EVENT = 2
const val URL = "https://www.google.com+$EVENT"
}
}
fun compileTest(){
println(CompileExample.URL)// this is equal to println("https://www.google.com+2")
}
// <========================== Multi line String =========================>
//used withing triple quotes
fun main(){
/*val string = "This is" +
"a " +
"multi" +
"line" +
"string"
println(string)*/
val string = """This
this
this
dfas
"""
println(string)
}
// <========================== Higher order functions =========================>
//Functions can be stored in Class fields, local fields inside function, can be passes as parameter to other
//functions or class constructors.
// Function type syntax ==> ({parameters goes here}) -> {Return Type}
//ex: (String) -> Boolean ==> A function that takes String as an argument and returns a Boolean
val abc: () -> Unit = {
}
fun higherOrderFunctions(){
//Parenthesis optional if last parameter is lambda/func
val dog: Dog = Dog()
//With parenthesis
dog.setDetailsInterface(10, {
//do something
})
//Without parenthesis
dog.setDetailsInterface(10) {
//do something
}
dog.setDetailsInterface(10, abc)
//DetailsInterface is from Java and is SAM construct (it has single abstract method). So it can used as lambda.
//All lambdas can be used as function in Kotlin.
}
// <========================== Higher order function examples =========================>
//Functions can be called using () or invoke()
//inline means, the function body will be replaced in call site.
//inline is used with higher order functions for performance.
inline fun Any.log(msg: () -> String) {
if (BuildConfig.DEBUG) {
Log.d("${this::class.java.simpleName}: ", msg())
//or
Log.d("${this::class.java.simpleName}: ", msg.invoke())
}
}
class LogTest(callback: () -> Unit) {
private val logMsg =
{
"something"
}
fun testlog() {
log(logMsg)
log { "something" }
log({ "something" })
//Arrays.toString won't even be called for Release build.
log {
Arrays.toString(arrayOf(1,2,3))
}
}
}
fun viewClickListenerTest(){
val view = TextView(this)
//Higher order function with argument syntax.
val clickListener = { view: View->
//do something
}
view.setOnClickListener(clickListener)
}
fun runAsync(bgBlock: ((DogKt) -> Unit)?) {
Thread(object : Runnable {
override fun run() {
//do network call
val dog = DogKt("")
if (bgBlock != null) {
bgBlock(dog)
}
//or
bgBlock?.invoke(dog)
}
}).start()
}
fun mainTest(){
runAsync {
print("success")
}
}
inline fun <R> tryWith(sendNonFatal: Boolean = true, fragileCode: () -> R?): R? {
try {
return fragileCode()
} catch (e: Exception) {
if (sendNonFatal) {
// Analytics.setNonFatalException(e)
}
if (BuildConfig.DEBUG) {
e.printStackTrace()
}
return null
}
}
fun tryWithTest(){
val json = tryWith(sendNonFatal = false) { JSONObject("some json") }
}
inline fun <R> R?.orElse(block: () -> R): R {
return this ?: block()
}
fun orElseTest(){
val dog: Dog? = null
val anotherDog: Dog? = null
dog?.name?.length
?: anotherDog?.name?.length ?: 0
//or
dog?.name?.length
.orElse { anotherDog?.name?.length ?: 0 }
}
// <========================== TypeAlias =========================>
//give alternate name to some type (can be class or function)
typealias NewDog = Dog
typealias Callback = () -> Unit
fun typeAliasTest(){
val dog = NewDog()
val callback: Callback = {
}
dog.setDetailsInterface(1, callback)
}
fun runSomething(callback: Callback){
callback()
}
// <========================== Higher Order Functions with Receivers =========================>
fun List<String>.filterWithReceiver(condition: String.() -> Boolean): List<String> {
return this.filter { condition(it) }
}
fun receiverTest() {
val list = listOf("a", "abcd", "cd", "hello", "hi", "apple")
val newList = list.filterWithReceiver {
this.startsWith("a")
}
println(newList)
}
inline fun SharedPreferences.edit(
action: SharedPreferences.Editor.() -> Unit
) {
val editor = edit()
action(editor)
editor.apply()
}
fun sharedPreferenceTest(){
appContext.getSharedPreferences("file_name", Context.MODE_PRIVATE)
.edit {
putBoolean("someBoolean", false)
putString("someString", "something")
}
}
inline fun View.runOnViewTreeObserver(crossinline action: () -> Unit) {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
viewTreeObserver.removeOnGlobalLayoutListener(this)
} else{
viewTreeObserver.removeGlobalOnLayoutListener(this)
}
action()
}
})
}
fun viewOnLayoutTest(){
val view = TextView(this)
view.runOnViewTreeObserver {
}
}
package com.muthuraj.kotlinBasics.kotlinbasics
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
class MainActivity : AppCompatActivity() {
//findViewById will be called on first time access of textView
private val textView: TextView by lazy { findViewById<TextView>(R.id.text_view) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onStart() {
super.onStart()
//lazy block is executed now
textView.text = "start"
}
override fun onStop() {
super.onStop()
//textView is cached from previous initialization
textView.text = "stop"
val string = " \"data\" : { \"key\" : \"value\" }"
string.toJson()
}
}
class MainFragment : Fragment() {
private lateinit var textView: TextView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.activity_main, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
textView = view!!.findViewById(R.id.text_view)
}
}
/* $Id$ */
package com.muthuraj.kotlinBasics.kotlinbasics
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
/**
* Created by Muthuraj on 2019-04-14.
*
* Jambav, Zoho Corporation
*/
class ChatAdapter : RecyclerView.Adapter<ChatViewHolder>() {
var data = emptyList<ChatData>()
fun updateData(newData: List<ChatData>) {
data = newData
notifyDataSetChanged()
}
override fun getItemViewType(position: Int): Int {
return when (data[position]) {
is ChatData.Date -> R.layout.chat_date
is ChatData.UnreadHeader -> R.layout.chat_unread_header
is ChatData.SentMessage -> R.layout.chat_sent
is ChatData.ReceivedMessage -> R.layout.chat_received //else case is not needed since we covered all cases
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChatViewHolder {
val inflater = LayoutInflater.from(parent.context)
return ChatViewHolder(inflater.inflate(viewType, parent, false))
}
override fun onBindViewHolder(holder: ChatViewHolder, position: Int) {
val chatData = data[position]
when (chatData) {
is ChatData.Date -> {
chatData.text //set this in UI
}
is ChatData.UnreadHeader -> {
chatData.text //set this in UI
}
is ChatData.SentMessage -> {
chatData.message //set this in UI
}
is ChatData.ReceivedMessage -> {
chatData.message //set this in UI
}
}.consumeWhen() //without this method call, there will be no compile error if extra states are added to ChatData
}
override fun getItemCount() = data.size
}
sealed class ChatData {
data class Date(val text: String) : ChatData()
data class UnreadHeader(val text: String) : ChatData()
data class SentMessage(val senderName: String, val dateTime: String, val message: String) : ChatData()
data class ReceivedMessage(val senderName: String, val dateTime: String, val message: String) : ChatData()
}
class ChatViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
package com.muthuraj.kotlinBasics.kotlinbasics;
/**
* Created by Muthuraj on 2019-03-13.
*/
public class SingletonExample {
private static final SingletonExample ourInstance = new SingletonExample();
public static SingletonExample getInstance() {
return ourInstance;
}
private SingletonExample() {
}
}
/* $Id$ */
package com.muthuraj.kotlinBasics.kotlinbasics
/**
* Created by Muthuraj on 2019-03-13.
*/
object SingletonExampleKt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment