Showing posts with label Android. Show all posts
Showing posts with label Android. Show all posts

Monday, August 21, 2017

Android with Kotlin: Using Lambda Expressions

The lambda expressions that we will see in Kotlin, are not really a complete novelty ..., in Java they can be used and it is something that other languages like C # already have it from approximately the year 2006 (with .Net 3.0 ).

But what are lambda expressions?

Lambda expressions allow you to pass functionality as an argument in a very simple way and without having to use anonymous classes. This makes coding a lot simpler.

Suppose we have the following function:

fun compare(a: String, b: String): Boolean = a.length < b.length

Mediante una expresión lambda se podría hacer los siguiente:

max(strings, { a, b -> a.length < b.length })

"Max" is a function that takes the value of the second argument, where this second argument is itself a function.

The general format of a lambda expression is:

{
   Param1, param2 -> // parameters separated by comma
   Param1 + param2 // code to execute
}

To finish this with a very practical example, let's first consider the implementation of an "OnItemClicListener" in a ListView in Java, traditionally it would look like this:

mListView.setOnItemClickListener(new OnItemClickListener() {
  @Override
  public void onItemClick(AdapterView<?> parent, View view,
  int position, long id) {

  Log.d("onItemClick", "Se hizo clic") // my code.

  }
});

With a lambda expression in Kotlin, it would be simplified this way:

mListView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->

    Log.d("onItemClick", "Se hizo clic") // my code.

}

As you can see, the difference in simplicity and reduction of code is extremely appreciable. However, suppose that view and id are parameters which will not be used, the expression could be simplified even more by replacing those arguments that will not be in use by an underscore:

mListView.onItemClickListener = AdapterView.OnItemClickListener { parent, _, position, _ ->

    Log.d("onItemClick", "Se hizo clic") // my code.

}

Even better, suppose the following classic example of the OnClickListener of a button in Java:

button.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v){

doSomething();

}
});

In Kotlin, it is reduced to a single line:

button.setOnClickListener({ view -> doSomething() })

If the parameters are not used, directly instead of replacing them with an underscore, you can remove them, leaving:

button.setOnClickListener({ doSomething() })

Finally, since the parameter function is unique and the lambda too, I can remove the parentheses with:

button .setOnClickListener { doSomething() }

Something to point out is that Android Studio itself is guiding us and, if it finds that we can replace the code we write for a lambda expression, we next update it automatically by the hand of the "yellow lamp" that usually appears on the margin Left of our code.

Kotlin Lambda Expressions

You can see a complete and implemented example of this and other issues, in the following application that I left complete in Github:

https://github.com/paveliz/ClimaApp_en_Kotlin

Ver la versión en Español de este artículo acá:

https://paveliz.blogspot.com.ar/2017/08/android-con-kotlin-usando-lambda.html

Thursday, September 3, 2015

Managing two fragments in a simple example

When I started to study fragments on Android, I discover the following example on the Developer Android Site: http://developer.android.com/guide/components/fragments.html

Basically, 1 Activity that change two fragments according the layout. It's sounds very useful but this documentation lacks of code that can help me to understand how to create this kind of layouts and fragment interaction.

This is because I created this small example focused on solve the two fragments interaction with 1 main layout.


1) Layouts

I created two activity_main.xml layouts, one in the "layout" folder (default) and the second one in the "layout_land" folder. Android will use this layout on screen rotation to landscape.

activity_main.xml (portrait)

The main layout in portrait mode, will only include the main fragment directly.

activity_main.xml (landscape)

The main layout in landscape mode, will include the main fragment and a second framelayout that I will use as a "container" for the second fragment that will be added programmatically. 

Notice that this layout use a LinearLayout with an Horizontal Divider and of course, Horizontal orientation:

android:divider="?android:dividerHorizontal"android:orientation="horizontal"

Also, notice that I'm using the "android:layout_weight" property according the Android Developer documentation: http://developer.android.com/guide/topics/ui/layout/linear.html#Weight

2) Second fragment detection

Because the main activity will use the both activity_main.xml according the layout orientation I need to find a way to detect if I'm using the layout with one fragment or the layout with two fragments, because if not..., well..., nothing it's going to work well.

To do this, I basically "ask" with the following line if the second framework exists or not:

if (findViewById(R.id.fragment_detail)!=null)

If this conditions its "True", it's because I'm in landscape mode and I'm using the Two Fragments Layout so I need to call the second fragment and show it. If not, there is nothing to worry, because I'm using the main fragment layout that it's already included and called in the layout.

As a result, the main activity will add the second fragment only when he detect need to do it.

3) Fragment calls a method in the Activity (NO hardcoding)

I need to find a way to manage the OnItemClickListener from the ListView in the DetailFragment but calling a method in the MainActivity.

Why?

Basically:

a) I don't want to put references or calls to others Activities inside the OnItemClickListener event in the DetailFragment. It supposed that fragments need to be "reusable", so you should not put references to external activities inside.

b) I want to call an independent method created in the MainActivity from the OnItemClickListener event in the DetailFragment but, I don't want to create a "hardcoding" relationship between both parts. Because again..., I don't know who is going to reuse this fragment in the feature calling it from another activity!

The Result:
- I created an Interface that includes a method.
- I implemented this method in the MainActivity.
- I got an instance of the Activity that creates the DetailFragment in the "onAttach" event inside the DetailFragment.
- I used the instance to access the method that then is called in the ListView.
This is a "clear" way to call a method from a Fragment to an Activity without compromise the independence of the fragment.

As a result, I created what I understand it's a very simple example that covers:

- Managing different layouts between landscape and portrait.
- Implementing and reusing fragments between layouts.
- Uncouple methods calling between fragments and activities.

Main Layout in Portrait:

 


Main Layout in Landscape:





Hope it helps you to understand these concepts. But if you find any doubts or if you find any issue or suggestions to improve this example, please, don't hesitate to contact me.