Sunday, 9 July 2017

Android Launch Mode

Activity is one of the most brilliant concept on Android from its well-design architecture on memory management which lets Multitasking works perfectly on this most popular mobile operating system. Anyway, Activity is not just to be launched on the screen. The way it is launched is also concerned. There are so many details in this topic. One of those that is really important is launchMode, which is the one that we are going to talk about in this blog.


There are 4 types of launchMode available. Let's see it one by one.
1. Standard
2. SingleTop
3. SingleTask
4. SingleInstance

1. Standard:  This is the default mode.  We are adding launchMode=”standard” in B.

Assume Activity Stack
D
C
B
A

Start Activity B again, Now the activity stack will be
B -new instance of B
D
C
B
A

2. SingleTop:  We are adding launchMode=”singleTop” in D.

Eg:1
Assume Activity Stack
D - is on top of Activity Stack
C
B
A

Start D from any service or other application or from somewhere.
Output:
D -old instance gets extras data through onNewIntent(Intent intent);
C
B
A

Note: if the activity available in the top of stack, it will update the same instance with new intent data or else it will create a new activity instance.

Eg: 2
Assume Activity Stack
D
C
B
A

Start C from D
Output:
C -As the last C was not on the top of task, so new instance will be created.
D
C
B
A

3. SingleTask: We are adding launchMode=”singleTask” in C.

Assume Activity Stack
D
C
B
A

Start C from any activity or service
Output:
C -old instance gets extras data through onNewIntent(Intent intent);
B
A

Note: it checks whether Activity C is available in the Stack, if yes, update the instance with new data and destroy the other activity at the top. Hence here Activity D gets destroyed.  if activity is unavailable in the stack it create a new instance as usual.

4. SingleInstance: We are adding launchMode=”singleInstance” in E.

Eg 1:
Assume Activity Stack
D
C
B
A

Start E
Output:
E
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
D
C
B
A

Note: A , B , C , D will be in one task and E will be in another task.
and if we continue this,  start F from E,then

Output:
F
D
C
B
A
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -
E

Note: A , B , C , D , F will be in one task and E will be in another task.

Eg 2:
Assume Activity Stack
A
B
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -
E

Start E from A
Output:
E -old instance gets extras data through onNewIntent(Intent intent);
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
A
B

Courtesy: Link1 & Link2

Android Flags Launch Mode

These flags has been setted programmatically, it can be used depends upon to the situation and it does overrides the behaviour which has defined in the AndroidManifest.xml file.

The following are the list of launch mode flags

FLAG_NEW_TASK
FLAG_CLEAR_TASK
FLAG_SINGLE_TOP
FLAG_CLEAR_TOP



FLAG_NEW_TASK:

Eg 1:
Assume Activity Stack
D
C
B
A

We are starting E from D with flag
Output:
E
-------
D
C
B
A
Note:  A , B , C , D will be in one task and E will be in another task

Eg 2:
Assume Activity Stack
D
C
B
A

We are starting B from D with flag
Output:
B
-------
D
C
B
A
Note:  A , B , C , D will be in one task and and another B will be in another task

FLAG_CLEAR_TASK: It works in conjugation with FLAG_NEW_TASK

Assume Activity Stack
D
C
B
A

We are starting E from D with flag
Output:
E

Note: All other activities will be get destroyed, every time it creates the new instance of the activity. Importantly, even if the activity already exist in the stack, it won't encourage the updating of the same activity with onNewIntent(...)

FLAG_SINGLE_TOP:
This works same as launch mode="singleTop" (Refer this link)

FLAG_CLEAR_TOP: It works similar to the SingleTop Flag, but it has one unique feature of destroying the activities on the top of the stack

Assume Activity Stack
D
C
B
A

We are starting B from D with flag
Output:
B -old instance gets extras data through onNewIntent(Intent intent);
A
Note: All the other activities on top of the B will be destroyed.

Courtesy: Link

Sunday, 2 July 2017

Kotlin: tailrec - Permanent fix for Painful StackOverflowError



Parameters and local variables are allocated on the stack (with reference types the object lives on the heap and a variable references that object). The stack typically lives at the upper end of your address space and as it is used up it heads towards the bottom of the address space (i.e. towards zero).

Your process also has a heap, which lives at the bottom end of your process. As you allocate memory, this heap can grow towards the upper end of your address space. As you can see, there is a potential for the heap to "collide" with the stack (a bit like tectonic plates!!!).

The common cause for a stack overflow is a bad recursive call. Typically, this is caused when your recursive functions doesn't have the correct termination condition, so it ends up calling itself forever. However, with GUI programming, it's possible to generate indirect recursion. For example, your app may be handling paint messages, and, whilst processing them, it may call a function that causes the system to send another paint message. Here you've not explicitly called yourself, but the OS/VM has done it for you.

To deal with them you'll need to examine your code. If you've got functions that call themselves then check that you've got a terminating condition. If you have then check than when calling the function you have at least modified one of the arguments, otherwise there'll be no visible change for the recursively called function and the terminating condition is useless.

If you've got no obvious recursive functions then check to see if you're calling any library functions that indirectly will cause your function to be called (like the implicit case above).

Courtesy: Link1

Example:  This is a demo example which i have used to get the StackOverflowError
Wrote a long run recursive method to sum up-to n numbers.

// Recursive function to find sum of numbers
fun sumOfNumbers(aVal:Int):Int {
    sum+=aVal;
    if (aVal == 0)
        return sum  
    else      
        return sumOfNumbers(aVal-1)
}
print(sumOfNumbers(3)) // 3+2+1=6  - This won't cause StackOverflowError
Output: 6

See, here we have used the smaller number, assume i trying to give a larger number (it may differ based on the system memory), While I'm testing with the below scenario got caught with the StackOverflowError at 1023...1050 (randomly).

print(sumOfNumbers(9000))  // 9000+8999+8998...  - This cause StackOverflowError

Hence, In order to avoid this kind of issue, kotlin provides an option called tailrec, we need to add this keyword before to the recursive method, the rest will taken care by the kotlin internally do the looping kind of approach and facilitates to provide us the solid & valid output with out any crash or error.

// Same Recursive function to find sum of numbers using tailrec 
tailrec fun sumOfNumbers(aVal:Int):Int {
    sum+=aVal;  
    if (aVal == 0)
        return sum  
    else      
        return sumOfNumbers(aVal-1)
}

print(sumOfNumbers(9000))   // The tailrec keyword take care of the app crash or SOF error.
Output: 040504500

Kotlin - Extension Vs Infix

Extension:
Kotlin, similar to Objective C (Categories) & C# Extension methods, here kotlin provides the ability to extend a class with new functionality without inheriting the class i.e. by using the Decorator design pattern. This is done via special declarations called extensions. Kotlin supports both extension functions and extension properties.

Infix Function:
In Simple, All Extension functions are not Infix, but every Infix method must to be extension function.

Criteria: 
0. Mandatory to have a params to the function,
1. Function does not accept more than one params.

// Definition: Extension function, here we have extending the checkCastMyVote from the String Class (In-Built Class).
// Here the function is used as an expression.

fun String.checkCastMyVote(name: String, age: Int) =
        if (age >= ELIGIBLE_YEAR) {
            "$this $name your age is $age, you are eligible to cast your vote"
        } else if (age in 0..17) {
            "$this $name you need to wait for ${ELIGIBLE_YEAR.minus(age)} more year(s)"
        } else {
            "$this $name, please provide the valid birth year (Given: $age)"
        }

// Calling a Extension Function: 
println("Mr.".checkCastMyVote("Ragavan", 23))  // Passing a params
println("Mr.".checkCastMyVote(age = 42, name = "Rajeevan"))  // Named functions


// Infix function definition
infix fun Int.getAge(yob: Int) =
        if (yob > 0) {
            this.minus(yob)
        } else {
            yob
        }

// Infix function call (no need to use dot or typical function calling syntax)
val CURRENT_YEAR=2017
var YEAR_OF_BIRTH=1988
var age = CURRENT_YEAR getAge YEAR_OF_BIRTH

Also, we can also apply & access this both extension and infix function to the user defined classes as well.

// Defining the class
class Guru {
    var name: String = ""
    fun isPassed(totalMark: Int) = if (totalMark > 35) "Passed" else "Failed"
}

// Defining the infix function.
infix fun Guru.isScholarshipEligibleMessage(totalMark: Int) =
        when (totalMark) {
            in 0..34 -> "No scholarship available for ${this.name} "
            in 35..50 ->
                "${this.name} Avail 50% Scholarship of amount"
            in 51..80 -> "${this.name} Avail 70% of Scholarship amount"
            in 81..100 -> "${this.name} Avail 85% of Scholarship amount"
            else -> "${this.name} Total Mark is invalid"
        }


// Calling the method
 var guru = Guru()
    guru.name = "Rajeev Menon"
    var totalMarks = 0 //38 //79 //85
    println("${guru.name} is ${guru.isPassed(totalMarks)}")
    println(guru isScholarshipEligibleMessage totalMarks)