قالب وردپرس درنا توس
Home / IOS Development / Introduction to Kotlin Lambdas: Getting started

Introduction to Kotlin Lambdas: Getting started



In this tutorial you will learn how to use lambda expressions and other functional letters provided by Kotlin for the Android platform.

Lambda expression is a simplified representation of a function. It can be transferred as a parameter, stored in a variable or even returned as a value.

To practice lambda expressions, you'll build a simple app to save and manage your favorite songs. It will have the functionality to:

  • Add songs to a favorite list.
  • View favorite songs in a list of the playlist range.

  Cassette Starter UI

While doing so, you will explore the following Kotlin topics:

  • Lambdas
  • Anonymous features
  • Higher order functions
  • Close

Time to begin to learn!

Getting Started

Use Download the materials button at the top or bottom of this tutorial to download the startup project.

When the project is downloaded:

  1. Open the startup project in Android Studio 3.3 or later.
  2. Press Command + 1 on Mac (or Alt + 1 on Windows) to open the project structure.
  3. Open java and res directories.

Take a moment to review the most important project files to learn more about their use. [19659002]

  • MainActivity.kt : Displays all the songs you have added to the user interface. Initially, it shows an empty screen for which there is no data.
  • AddSongFragment.kt : Displays the user interface to specify and save song details.
  • SongStore.kt : Help class to manage and save songs in Preferences.
  • activity_main.xml : Layout file for song list UI.
  • Dialog + R [or + + F10 on Windows) to run the app on an emulator or device.

    Recovery Features

    A function is a group of statements written to perform a particular task.

    Open the file MainActivity.kt and add the following code under onCreate () function:

      // 1
    private fun showAddSongDialog () {
    // 2
    AddSongFragment.show (supportFragmentManager)
    }
    

    Here, you:

    1. Define a function called showAddSongDialog using funny keywords. The function takes no parameters and returns no value.
    2. Call the function () in AddSongFragment to display Add Song ]

    Build the project and run on emulator or device.

     Cassette Starter UI

    Click Add the song button. Nothing happens. This is because you still have to put the listeners on the buttons.

    Then you will add lambda expression to the app. You will use them to put clicks on listeners and also add some text style to the song list.

    Getting Into the Lambda Expression

    A [lambda] lambda expression is a shorter way of describing a function. It doesn't need a name or a return statement. You can store lambda expressions in a variable and perform them as common functions.

    You define lambda expressions that follow this syntax:

      select lambdaName: Type = {parameterList -> codeBody}
    

    Function Types

    Function types are notation that resembles a function signature. A function type has a parameter list within parentheses and a return type. For example, (A, B) -> C represents a function that takes two parameters of the type A and B and returns a value of the type C . You can also specify blank parameter lists and no return value with Device .

    Example :

      // 1
    choice lambda1: () -> Unit = {println ("hello, world")}
    // 2
    choice lambda2 = {println ("hello, world")}
    // 3
    lambda2 ()
    

    In the example code above, you are:

    1. Assign the lambda expression to a variable lambda1 . It has a function type () -> Unit . The type represents a function that does not take any parameters and returns no value or Device .
    2. Assign another lambda expression to another variable lambda2 . You find that the variable type can be ignored for simple lambda expressions thanks to Kotlin Type Inference .
    3. Perform the lambda expression in the same way as feature calls.

    Lambda with parameters

    A lambda expression can have one or more parameters. You specify the parameters before the symbol followed by codeBody . The compiler interprets return type lambda at the last executable sentence in its body:

    You specify lambda expressions in the following formats:

      // 1
    selection lambda1: (String) -> Unit = {name: String -> println ("Hi, $ name")}
    // 2
    selection lambda2: (String) -> Unit = {name -> println ("Hi, $ name")}
    // 3
    drop lambda3: (String) -> Unit = {println ("Hi, $ it")}
    // 4
    selection lambda4: (String) -> Unit = {println ("Hi, World!")}
    // 5
    drop lambda5: (Int, Int) -> Int = {x, y ->
    print (x)
    print (y)
    x + y
    }
    // 6
    fall lambda6 = {x: Int, y: Int -> x + y}
    

    In the above examples, you learn:

    1. lambda1 stores a lambda that takes a parameter of type String and returns no value.
    2. lambda2 shows that you can ignore the lambda parameter type as it is already specified by the variable function type.
    3. In lambda3 the parameter name and are skipped and instead there are keywords used. it can be used to refer to the parameter of lambdas with only one argument.
    4. In [lambda4] you use the same structure as lambda3 but in this case you do not use the parameter String . [Lambda5] type declaration of variable represents a function with two parameters of the type Int with the return type also as Int . In this example, you have a block code with several instructions. The last statement of lambda x + y helps the compiler to derive the return model of lambda. [Lambda6] represents the simplified form of lambda5 .

    Next you will examine the lambda expression use cases in the app.

    Making Buttons Clickable

    Open MainActivity.kt . It displays an empty user interface with a Add Song button. Add the following function under showAddSongDialog () :

      // 1
    private fun setClickListeners () {
    // 2
    button_add_song_empty.setOnClickListener {
    showAddSongDialog ()
    }
    // 3
    button_add_song.setOnClickListener {
    showAddSongDialog ()
    }
    }
    
  • After adding the code above, press Opt + Type (or Alt + Write on Windows) to import ] button_add_song_empty and button_add_song references about Android Studio do not do it automatically.

    In this code you are:

    1. Define a function setClickListeners () to add clicks to listeners to buttons.
    2. Using Kotlin extensions, you click clicks to button_add_song_empty . According to the documentation of View.OnClickListener interface, there is a single function to implement. You can replace such interface implementations with lambdas. Also, as lambda is the only and last parameter of the setOnClickListener function, it can be moved outside the parentheses.
    3. Set clicks to button_add_song button, which appears when the blank User Interface is hidden.

    Understanding Lambda Concepts

    Lambdas has two special properties.

    First, onClickListener () that you just defined has been written in this other way:

      button_add_song_empty.setOnClickListener (View.OnClickListener {
    showAddSongDialog ()
    })
    

    As you can see, lambda is defined in parenthesis as a parameter. If a lambda has a function as the last or only parameter, you can omit the parentheses as you did in the previous code.

    The second feature is that you can replace interfaces with a single method with a lambda expression. You can check the Android documentation on View.OnClickListener to see that View.OnClickListener is an interface with only one method: onClick (View v) .

    Finally call ] setClickListeners () from the function onCreate () in MainActivity :

      setClickListeners ()
    

    Build and run and click the Add Song button again. You will see the dialog box to add a new song.

    Then you will add logic to display songs and hide empty user interfaces.

    Hide the empty user interface

    The MainActivity class initially shows an empty screen. You must hide the blank user interface when you start adding songs.

    In the file MainActivity.kt add the following lambda expressions as a new property under private sentinit was songStore: SongStore ] to change the blank interface's visibility:

      // 1
    select toggleEmptyView = {show: Boolean ->
    // 2
    group_empty.visibility = if (show) View.VISIBLE else View.GONE
    button_add_song.visibility = if (view) View.GONE else View.VISIBLE
    }
    In the above code, you are: 

    1. Define a lambda having a parameter of Boolean type.
    2. Show the empty user interface if value is true otherwise do it.

    Then you will add the code to display songs from SongStore on the user interface.

    Showing songs

    As stated earlier, SongStore.kt stores the song for preferences. It stores each song as a comma-separated String element in StringSet preference in the format title, artist, year .

    The class SongStore gives you a property allSongs to access all stored songs. You will now add the code to display the song list on the screen. You will also add some styling to the song list by emphasizing the song title.

    In the file MainActivity.kt and add the following function under setClickListeners () method to display available songs. Don't forget to import required classes with Opt + Write (or Alt + Write on Windows):

      / / 1
    private fun showAllSongs (singer: List ) {
    // 2
    selection span = mutableListOf  ()
    // 3
    fall underlineTitle: (String) -> SpannableString = {
    fall songTitle = it.split (",") [0]
    SpannableString (it) .apply {
    setSpan (UnderlineSpan (), 0, songTitle.length,
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE)
    }
    }
    // 4
    for (song in songs) {
    spans.add (underlineTitle (song))
    spans.add (SpannedString ("n"))
    }
    // 5
    text_view_all_songs.text = TextUtils.concat (* spans.toTypedArray ())
    // 6
    toggleEmptyView (spans.isEmpty ())
    }
    

    In this code you are:

    1. Define function showAllSongs () which takes a list of songs as a parameter.
    2. Initialize list of Spanned to keep each style song object.
    3. Define lambda expressions that take a parameter of String and have a return type on SpannableString . Lambda finds the song title by sharing the song on and reading the first value. Then the underlined applies to each song title.
    4. Use the subline style of each song title by transferring each song to underlineTitle the lambda variable as underlineTitle (song) . You also add a new line track to add spaces between song items in the user interface.
    5. Show the song list on the user interface by joining all spans and set it to text_view_all_songs see.
    6. Replace the empty user interface by calling toggleEmptyView based on whether the stylish song item list is not empty.

    Upload songs

    In the file MainActivity.kt add the following line under setClickListeners () call the function onCreate () :

      ] showAllSongs (songStore.allSongs.toList ())
    

    In this code block, call showAllSongs and send the current stored songs by reading the store.allSongs.toList () value from the SongStore class.

    Also add the following code in the function onSongAdded :

      showAllSongs (songStore.allSongs.toList ())
    toggleEmptyView (false)
    

    1. The function onSongAdded is called AddSongFragment each time a new song is added.

      In the above code, showAllSongs is referred to as the current stored songs from the SongStore class. You also change the empty user interface.

      Save your changes and run the app. No songs are visible yet SongStore is still empty. Next, you will proceed and add the code to handle the addition of songs.

      Anonymous Features

      As you have learned in the previous paragraph, lambda expressions cannot have a return task. The return type is either extracted from the variable that stores lambda or from the last sentence of the lambda body. Another missing thing is several return points you may often need.

      You can use anonymous features to solve these shortcomings. You define an anonymous function as a regular function without giving its name.

      Once you have entered the song title, artist and year in the input fields on the screen, click Save the button.

      Nothing happens yet, since you still need to add the code to read and save the input song. Then add the code to save the song when you click the Save button.

      Save songs

      Open the file AddSongFragment.kt and add the following code under handleSongSaveClick () function to read input data:

        // 1
      private fun storageSong (): Boolean {
      // 2
      fall title = edit_text_title.text? .toString ()
      choice artist = edit_text_artist.text? .toString ()
      choice year = edit_text_year.text? .toString ()
      
      return true
      }
      

      1. In this code you are:

        1. Define a function for saveSong () with a boolean type.
        2. Read and store the input values ​​in the respective variables. You save the title, artist and year of the title artist year variables.

        Next, you will add the following code into ] onClickListener {19459017] block code defined in handleSongSaveClick () to call the function saveSong every time you click the Save button :

          if (saveSong ()) {
        dismiss()
        }
        

        Here you reject the input screen dialog if saveSong () returns true .

        You may be wondering why the function saveSong () returns a boolean value. Then, find out why validation is important and case for anonymous functions.

        Validation of Song Data

        When taking user input, it is necessary for you to validate the input data and ensure that the data is accurate and consistent. Inconsistent data leads to crashing and bad user experiences.

        Add the following code under the function saveSong () in the file AddSongFragment.kt . You must validate the input data using the following functions before saving it:

        
         // 1
        private fun isValidArtist (artist: String?): Boolean {
        // 2
        choice artistValidator = funny (value: String?): Boolean {
        // 3
        if (value.isNullOrEmpty ()) {
        showError (R.string.error_artist_empty)
        return false
        }
        
        if (value.length < 2) { 
            showError(R.string.error_artist_invalid) 
            return false 
          } 
          return true } 
          
          // 4 
          return artistValidator(artist) 
        } 
        
        // 5 
        private fun isValidYear(year: String?): Boolean { 
          val yearValidator: (String?) -> Boolean = {! it.isNullOrEmpty () && it.toInt () in 1877..2019}
        return yearValidator (year)
        }
        

        1. In the code block above, you find:

          1. Define a function isValidArtist () with Boolean return type.
          2. Initialize artistValidator variable with an anonymous function.
          3. Return false if the entry value of the artist name is zero or empty or if the length is less than two characters. Otherwise, return true from the anonymous function.
          4. Perform the anonymous function by calling artistValidator () and passing artist as parameter.
          5. Define a function isValidYear () that returns a true or false value. It calls lambda yearValidator at the annual value to validate the input data and returns the result.

          You must call these validation functions when a song is stored.

          Save data with validation

          In addition to AddSongFragment.kt file, add the following lines in saveSong () method before return statement: [19659030] if (title.isNullOrEmpty ()) { showError (R.string.error_title_empty) return false } if (! isValidArtist (artist)) { return false } if (! isValidYear (year)) { showError (R.string.error_year_invalid) return false }

        The above code returns false when any of the input fields have an invalid value. You reject the Add Song dialog when the saveSong () function returns true - there are no errors in the input values.

        Run the app . Click the Add Song button to add a new song. You will notice an error message if you specify an error year or when you keep the artist name field blank.

        Then, add a function to save the input song data into preferences.

        High order functions

        A higher order function is a function that takes functions as parameters and can also return a function. When invoking a higher order, you can send lambdas or anonymous functions as parameters.

        Open the file SongStore.kt and add the following function under getStoredSongs () function to save song details:

          // 1
        funny storageSong (song: String, onSuccess: (() -> Device)?, OnError: (Int) -> Device) {
        // 2
        select singer = getStoredSongs ()
        if (songs.contains (song)) {
        // 3
        onError (R.string.error_song_exists)
        } other {
        // 4
        songs.add (song)
        preferences.edit (true) {
        putStringSet (STORE_KEY, songs)
        }
        onSuccess? .invoke ()
        }
        }
        

        Remember to import the necessary dependencies with Opt + Type (or Alt + Write on Windows).

        In the code above code, you:

        1. Define a high-order function name saveSong () . It takes the first parameter song type String the second parameter is called onSuccess with a function type and the third parameter onError
        2. To duplicate, display an error by calling onError () function.
        3. Check if duplication happens by getting all the songs and checking if the new song already exists. 19659000] You must still call the function above from saveSong () in AddSongFragment AddSongFragment AddSongFragment AddSongFragment ] after validating the input data.

          Return to AddSongFragment.kt file and add the following code to the saveSong () method before the last return statement: [19659029] songStore.saveSong ("$ title, $ artist, $ year ", on SongAdded :: onSongAdded, this :: showError)

          In the above code, the function is called saveSong from the class SongStore and transmits the inputs after validation. The fourth parameter is a function reference to OnSongAdded interface function. The fifth parameter is a function reference to the function showError defined in AddSongFragment .

          Build and run . Finally, when you save a song, it is saved in Settings. The Add Song dialog box is rejected and the newly added song appears on the Home screen.

          Then add a function to find the annual break of your song playlist using Closures .

          Understanding Closures

          A closure is a lambda capable of reading and modifying the variables defined beyond its scope. It is also known as variable capture within lambda . It reduces code redundancy and improves overall readability.

          Return to MainActivity.kt and add the following code under the function showAllSongs () :

            // 1
          private fun gameLeggelisteYearRange (singer: List ) {
          // 2
          if (songs.isEmpty ()) {
          return
          }
          // 3
          var startYear = songs [0] .split (",") [2] .trim (). toInt ()
          var endYear = startYear
          // 4
          select findStartEndYear = {
          songs.forEach {song ->
          fall songYear = song.split (",") [2] .trim (). toInt ()
          if (songYear> endYear) {
          endyear = songYear
          } other if (sang Yes <startYes) {
          startYear = songYear
          }
          }
          }
          // 5
          findStartEndYear ()
          
          // 6
          text_view_total.text = "($ startYear - $ endYear) - Total: $ {songs.count ()}"
          }
          

          In the above code, you are:

          1. Define a function findPlaylistYearRange () . It takes a list of String as a single parameter.
          2. If there is no song, don't show anything.
          3. Enter the value of startYear for the year of the first song in the song list. You also define endyear corresponding to the startbook .
          4. Define a lambda expression to calculate yearly basis and save it in findStartEndYear variable. This lambda expression can access and change the values ​​of startYear and endYear defined outside the scope. This is referred to as a Lambda closure .
          5. Call the lambda expression to find yearly.
          6. Enter the year mark text for text_view_year_range view.

          You need to call this feature to see the year's range on the screen. [19659000] In the file MainActivity.kt add the following code below to the end of showAllSongs function:

            findPlaylistYearRange (songs)
          

          Build and distribute the app to check out the year of your playlist.

          Where to go from here?

          Congratulations! You learned many concepts about lambda and used them for your app. While developing Android apps, you can use lambda expressions yourself without knowing what they are because Android Studio helps you convert interfaces to lambda expressions whenever possible. Now you understand how Android Studio simplifies your code.

          You can use the Download Materials button at the top or bottom of this tutorial to download the final project.

          Be sure to keep up to date with our latest training programs on Android and Kotlin. You can take the Android and Kotlin learning pathway for a more comprehensive understanding of the Android apps.

          We hope it was fun to learn about lambdas. If you have questions and comments, please join the discussions in the forum.

          Good luck! :]


Source link