Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Android Development with Kotlin, Part 2 - Internet Services and JSON

179 views

Published on

- Language Understanding Services (Microsoft LUIS)
- Android Menus
- Web Service Client / REST & HTTP Request
- Threads & Multitasking
- AsyncTask
- Permissions
- JSON Parsing
- Dynamic Lists
- RecyclerView & Adapter
- Click Handling

Published in: Technology
  • Be the first to comment

Android Development with Kotlin, Part 2 - Internet Services and JSON

  1. 1. St. Pölten University of Applied SciencesSt. Pölten University of Applied Sciences Platzhalter für möglichen Bildeinsatz Android Development with Kotlin, Part 2 Internet Services & JSON Andreas Jakl Digital Healthcare FH St. Pölten Platzhalter für möglichen Bildeinsatz Version 1.3
  2. 2. Andreas Jakl ▪ Focus areas ▪ AR / VR, mobile apps, sensors, interaction technology, software architecture, open source developer (NFC, Bluetooth Beacons) ▪ Microsoft MVP (Most Valuable Professional) ▪ mobility.builders community: Mobile Developer After-Work Events ▪ Previous Experience ▪ Tieto, Start-up (Mopius), Nokia (Finland), Siemens Mobile (Munich), FH Hagenberg (Mobile Computing) Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten https://www.andreasjakl.com/ @andijakl andreas.jakl@fhstp.ac.at 2
  3. 3. Contents ▪ Language Understanding Services (Microsoft LUIS) ▪ Android Menus ▪ Web Service Client / REST & HTTP Request ▪ Threads & Multitasking ▪ AsyncTask ▪ Permissions ▪ JSON Parsing ▪ Dynamic Lists ▪ RecyclerView & Adapter ▪ Click Handling Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 3
  4. 4. LANGUAGE UNDERSTANDING SERVICE Control Computers using Natural Language Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 4
  5. 5. Natural Language Understanding ▪ Identify information from conversations ▪ Train scenarios you want to differentiate simply by supplying examples ▪ Extract information from free-form sentences: dates, locations, numbers & more ▪ Reinforcement learning for continuous improvement ▪ Usage ▪ Chat bots, speech, analyzing text, smart speakers ▪ Services ▪ Microsoft LUIS, Amazon Comprehend, Facebook NLP, Google Cloud Natural Language, Watson Natural Language Understanding Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 5
  6. 6. LUIS Architecture Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 6 client (phone) cloud (LUIS) 1. Client sends request to cloud. Query contained in URL. https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/<appid> ?subscription-key=<key>&q=Turn on lights HTTPS connection / GET request (REST)
  7. 7. LUIS Architecture Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 7 client (phone) cloud (LUIS) HTTPS connection / JSON response (REST) 2. AI analyzes request, responds with results in JSON
  8. 8. LUIS Architecture Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 8 client (phone) cloud (LUIS) 2. AI analyzes request, responds with results in JSON { "query": "turn on lights", "topScoringIntent": { "intent": "HomeAutomation.TurnOn", "score": 0.990858853 }, "entities": [ { "entity": "on", "type": "HomeAutomation.Operation", "startIndex": 5, "endIndex": 6, "score": 0.553411 } ] }
  9. 9. Create LUIS Service ▪ Follow instructions at ▪ https://www.andreasjakl.com/using-natural-language-understanding-part- 3-luis-language-understanding-service/ ▪ Create your own vocabulary! ▪ If you like, additionally test “Home Automation” prebuilt domain: https://docs.microsoft.com/en-us/azure/cognitive-services/luis/luis-get- started-create-app Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 9
  10. 10. ANDROID MENUS User Interaction, in a different way Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 10
  11. 11. Exercise: Create SmartHomeClient ▪ Create new project ▪ Empty Activity, Kotlin support ▪ Layout ▪ Change from ConstraintLayout to LinearLayout ▪ Add EditText, ScrollView + nested TextView Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 11
  12. 12. Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 12 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingLeft="16dp" android:paddingRight="16dp" android:paddingTop="16dp" tools:context="com.andresjakl.smarthomeclient.MainActivity"> <EditText android:id="@+id/et_query_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter your command" android:inputType="text"/> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp"> <TextView android:id="@+id/tv_results" android:layout_width="wrap_content" android:layout_height="wrap_content" tools:text="Results" /> </ScrollView> </LinearLayout>
  13. 13. Create Menu Resource ▪ Add title for menu action to strings.xml ▪ Create new menu: ▪ Right-click res > New > Android Resource File Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 13 <string name="send">Send</string> Android MainActivity.kt onOptionsItem Selected()
  14. 14. Add Menu Item ▪ Use designer to create “Menu Item” ▪ Handle menu item in MainActivity.kt ▪ Override onCreateOptionsMenu() Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 14 override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.main, menu) return true }
  15. 15. Handle Tapped Menu Item ▪ Override onOptionsItemSelected() ▪ Show toast ▪ Test! Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 15 override fun onOptionsItemSelected(item: MenuItem?): Boolean { val selectedMenuItem = item?.itemId if (selectedMenuItem == R.id.action_send_command) { // TODO: Show toast! return true } return super.onOptionsItemSelected(item) }
  16. 16. WEB SERVICE CLIENT REST & More – access URLs Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 16
  17. 17. Build Uri ▪ Uri.Builder (Android API) ▪ Creates well-formed URI ▪ Takes care of particulars (encoding invalid characters, ? or & query codes, …) ▪ Configure parameters & URLs ▪ Best practices for securely using API keys ▪ https://developers.google.com/console/help/api-key-best-practices Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 17 private val ENDPOINT = "https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/xxx"; private val APPKEY = "yyy";
  18. 18. Uri -> URL ▪ Create build function ▪ Add query parameters to base URL ▪ Convert Android Uri to Java URL Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 18 var builtUri = Uri.parse(ENDPOINT).buildUpon() .appendQueryParameter("subscription-key", APPKEY) .appendQueryParameter("q", queryText) .build() return URL(builtUri.toString()) private fun buildUrl(queryText : String) : URL { }
  19. 19. Make Search Query ▪ Create function to make search query ▪ Call from menu item handler Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 19 private fun makeSearchQuery() { var queryCommand = et_query_text.text.toString() var queryUrl = buildUrl(queryCommand) Log.d(TAG, queryUrl.toString()) }
  20. 20. HTTP Request ▪ Add helper function to your class Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 20 /** * This method returns the entire result from the HTTP response. * * @param url The URL to fetch the HTTP response from. * @return The contents of the HTTP response. * @throws IOException Related to network and stream reading */ fun getResponseFromHttpUrl(url: URL): String? { val urlConnection = url.openConnection() as HttpURLConnection try { val inStream = urlConnection.inputStream val scanner = Scanner(inStream) // Using pattern a (beginning of the stream) - force scanner to read // the entire contents of the stream into the next token string // -> buffers data, different data sizes are allowed, converts // from UTF-8 to UTF-16 scanner.useDelimiter("A") val hasInput = scanner.hasNext() return if (hasInput) { scanner.next() } else { null } } finally { urlConnection.disconnect() } }
  21. 21. Extend makeSearchQuery() ▪ Call new function after Uri conversion ▪ Test app! Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 21 android.os.NetworkOnMainThreadException var queryResults : String? try { queryResults = getResponseFromHttpUrl(queryUrl) tv_results.text = queryResults } catch (e: IOException){ e.printStackTrace() }
  22. 22. THREADS AND MULTITASKING Keeping the UI responsive Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 22
  23. 23. Multi-Threading Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 23
  24. 24. Single User Interface Thread Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 24
  25. 25. Networking Takes Seconds Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 25 Loading … App freezes No user interaction possible!
  26. 26. After ~ 5 Seconds Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 26 Loading … App freezes No user interaction possible!
  27. 27. Multi-Threading Within Your App Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 27 Perform work on secondary execution thread UI stays responsive Background thread: UI thread: progress and results
  28. 28. AsyncTask Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 28 Main / UI Thread Background Thread onPreExecute AsyncTask.execute() publishProgress… doInBackground onPostExecute Variable types (in AsyncTask definition)
  29. 29. Create AsyncTask Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 29 Main / UI Thread Background Thread onPreExecute AsyncTask.execute() publishProgress… doInBackground onPostExecute Variable types (in AsyncTask definition) inner class WebQueryTask : AsyncTask<URL, Void, String?>() { }
  30. 30. Create AsyncTask Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 30 Main / UI Thread Background Thread onPreExecute AsyncTask.execute() publishProgress… doInBackground onPostExecute Variable types (in AsyncTask definition) inner class WebQueryTask : AsyncTask<URL, Void, String?>() { } Kotlin: inner class may access members of outer class
  31. 31. Set Up AsyncTask ▪ Override doInBackground() ▪ Move getResponseFromHttpUrl() into WebQueryTask class Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 31 override fun doInBackground(vararg params: URL): String? { } Kotlin: vararg = variable number of parameters Note: change URL? to URL
  32. 32. Implement AsyncTask ▪ Similar to previous web service call ▪ Update UI when finished Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 32 override fun doInBackground(vararg params: URL): String? { var queryUrl = params[0] var queryResults : String? = null try { queryResults = getResponseFromHttpUrl(queryUrl) } catch (e: IOException){ e.printStackTrace() } return queryResults } override fun onPostExecute(result: String?) { tv_results.text = result }
  33. 33. Test! ▪ Start thread! ▪ Test app! Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 33 java.lang.SecurityException: Permission denied (missing INTERNET permission?) android_getaddrinfo failed: EACCES (Permission denied) private fun makeSearchQuery() { var queryCommand = et_query_text.text.toString() var queryUrl = buildUrl(queryCommand) Log.d(TAG, queryUrl.toString()) WebQueryTask().execute(queryUrl) }
  34. 34. PERMISSIONS Access sensitive data Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 34
  35. 35. Permissions ▪ Each app gets its unique Linux user ID ▪ Runs within its own instance of an Android runtime ▪ -> completely sandboxed ▪ -> request access to resources + data outside of sandbox ▪ Permission list ▪ https://developer.android.com/guide/topics/permissions/index.html ▪ Why not just request all permissions? ▪ Users get suspicious! ▪ Think of alternatives: using camera app through Intent -> no camera permission needed for your app Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 35
  36. 36. Network Permissions ▪ Add permission to AndroidManifest.xml ▪ Device: Android 6+ (API level 23+) & targetSdkVersion = 23+ ▪ Dangerous permissions acknowledged while app is running ▪ Normal permissions: granted automatically at install time, no prompts ▪ https://developer.android.com/guide/topics/permissions/normal- permissions.html ▪ Granted permissions can be revoked ▪ < 23: install-time permissions Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 36 <uses-permission android:name="android.permission.INTERNET"/>
  37. 37. Final Test! Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 37
  38. 38. Network Libraries ▪ More powerful libraries ▪ Include caching, compression, etc. ▪ Volley (Google) ▪ OkHttp ▪ Retrofit Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 38
  39. 39. Exercise ▪ Repetition: save state of TextView to survive screen rotation! Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 39
  40. 40. JSON PARSING Data Formats Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 40
  41. 41. JSON Parsing Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 41 { "query": "turn on lights", "topScoringIntent": { "intent": "HomeAutomation.TurnOn", "score": 0.990858853 }, "entities": [ { "entity": "on", "type": "HomeAutomation.Operation", "startIndex": 5, "endIndex": 6, "score": 0.553411 } ] } val parsedJson = JSONObject(result) tv_top_intent.text = parsedJson.getJSONObject("topScoringIntent")?.getString("intent") val entitiesArray = parsedJson.getJSONArray("entities") if (entitiesArray != null && entitiesArray.length() > 0) { tv_top_entity_type.text = entitiesArray.getJSONObject(0)?.getString("type") }
  42. 42. Exercise ▪ Add additional TextViews ▪ Parse JSON and extract information ▪ Check that your app doesn’t crash if entering strange text Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 42
  43. 43. DYNAMIC LISTS Populating better lists Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 43
  44. 44. Scrolling TextView? Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 44 Handle tap events on items? More complex layouts per item? Different fonts & images? Performance: keeping everything in memory? Animations & effects?
  45. 45. RecyclerView Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 45Image credits: Google, https://developer.android.com/training/material/lists-cards.html Ali Connors Brunch this weekend? I’ll be in your neighborhood doing errands… 15m Layout instance 1. Layout instance scrolls out of view queue TextView TextView TextView TextView Image Layout instance 2. Placed in queue Lorem ipsum dolor sit amet consectetur adipiscing elit… 17h Layout instance 3. Filled with new content & scrolls in again
  46. 46. RecyclerView RecyclerView Flow Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 46 Data source Adapter Provides new data to RecyclerView when needed Adapter binds data from data source to views ViewHolder Used to send views to RecyclerView LayoutManager Tells RecyclerView how to layout views
  47. 47. Kotlin: Data Class ▪ Only contains data, no operations ▪ Auto-created utility functions ▪ Generates properties (no more getters and setters) ▪ equals(), hashCode(), toString(), copy() ▪ https://kotlinlang.org/docs/reference/data-classes.html ▪ Comparison to Java: https://antonioleiva.com/data-classes-kotlin/ Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 47 data class PartData ( val id: Long, val itemName: String) Data source
  48. 48. Creating Demo Data ▪ Create some demo data in onCreate() of MainActivity Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 48 Data source var partList = ArrayList<PartData>() partList.add(PartData(100411, "LED Green 568 nm, 5mm")) partList.add(PartData(101119, "Aluminium Capacitor 4.7μF")) partList.add(PartData(101624, "Potentiometer 500kΩ")) // ...
  49. 49. Create List Item Layout ▪ New layout xml file: part_list_item.xml ▪ Layout: LinearLayout (vertical) ▪ Width: match_parent ▪ Height: wrap_content ▪ Padding: 16dp ▪ Child: 2x TextView ▪ Id 1: @+id/tv_part_item_name (larger text size) ▪ Id 2: @+id/tv_part_id (smaller text size) Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 49
  50. 50. Add RecyclerView ▪ Add RecyclerView to dependencies in build.gradle of app ▪ compile 'com.android.support:recyclerview-v7:26.1.0’ Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 50 RecyclerView dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.0.2' implementation 'com.android.support:recyclerview-v7:26.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' }
  51. 51. ViewHolder ▪ Create class PartAdapter ▪ Create child class ViewHolder inside PartAdapter ▪ Describes item view ▪ Stores metadata about its place within RecyclerView Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 51 class PartViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { // bind() = Custom function. Copies items from supplied instance of our // "PartData" data class to the "itemView" we got through the constructor fun bind(part: PartData) { itemView.tv_part_item_name.text = part.itemName } } ViewHolder Kotlin: this is actually the primary constructor. Declares and initializes properties (here: itemView). https://kotlinlang.org/docs/reference/classes.html
  52. 52. Adapter Tasks Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 52 Adapter 1. Return information, e.g., about the number of items getItemCount() 2. Create new view instances onCreateViewHolder() 3. Populate view items with data onBindViewHolder()
  53. 53. Adapter Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 53 AdapterRecyclerView Data source 1. Return information, e.g., about the number of items getItemCount() 2. Create new view instances onCreateViewHolder() ViewHolder 3. Populate view items with data onBindViewHolder() id itemName 100411 LED Green 568 nm, 5mm 101119 Aluminium Capacitor 4.7μF 101629 Potentiometer 500kΩ
  54. 54. Create Adapter ▪ Extend PartAdapter ▪ Derive from RecyclerView.Adapter<RecyclerView.ViewHolder> ▪ Let Android Studio write required member implementations ▪ Add parameter to PartAdapter: Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 54 Adapter (val partItemList: List<PartData>)
  55. 55. Implement PartAdapter Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 55 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { // LayoutInflater: takes ID from layout defined in XML. // Instantiates the layout XML into corresponding View objects. // Use context from main app -> also supplies theme layout values! val inflater = LayoutInflater.from(parent.context) // Inflate XML. Last parameter: don't immediately attach new view to the parent view group val view = inflater.inflate(R.layout.part_list_item, parent, false) return PartViewHolder(view) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { // Populate ViewHolder with data that corresponds to the position in the list // which we are told to load (holder as PartViewHolder).bind(partItemList[position]) } override fun getItemCount() = partItemList.size
  56. 56. Add RecyclerView to MainActivity ▪ Update activity_main Layout ▪ Delete “Hello World” text ▪ Add RecyclerView Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 56 <android.support.v7.widget.RecyclerView android:id="@+id/rv_parts" android:layout_width="match_parent" android:layout_height="match_parent" />
  57. 57. Wire Up RecyclerView ▪ 1. Assign LinearLayoutManager ▪ Measures and positions item views ▪ Linear list layout (default: vertical) ▪ 2. Optional optimization ▪ View contents do not change RecyclerView size Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 57 rv_parts.layoutManager = LinearLayoutManager(this) rv_parts.hasFixedSize()
  58. 58. Wire Up RecyclerView ▪ 3. Assign PartAdapter to RecyclerView ▪ Supply test data we created earlier Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 58 rv_parts.adapter = PartAdapter(testData)
  59. 59. Final Test! Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 59
  60. 60. RECYCLERVIEW & CLICK HANDLING Advanced Topics for the Pros Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 60
  61. 61. RecyclerView RecyclerView & Click Listener Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 61 Data source Adapter Click Listener ViewHolder ViewHolder ViewHolder bind() function assigns data & click handler callback to view holder instances Click event executes registered click handler callback function
  62. 62. Higher-Order Functions ▪ Function that ▪ Takes another function as parameter, or ▪ Returns a function ▪ Lambda ▪ Surrounded by { } ▪ Parameters -> Return type Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 62
  63. 63. Experiments I: Class with Parameters ▪ Create a class that has parameters ▪ Note that you can use the parameters as properties Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 63 /** * Defines a class with a constructor. Its parameters are automatically available * as properties in the class. Note that the keyword "constructor" is optional * and could be stripped. */ class ClassWithConstructorProperties constructor (var a: Int, var b: Int) { fun calculate() : Int { return a + b; } } // Create new class instance var calcTest = ClassWithConstructorProperties(10, 20) // Print calculation results Log.d("Tests", "Calculation result: " + calcTest.calculate())
  64. 64. Experiments II: Function Parameters ▪ Define a function with a function parameter ▪ Specify structure the supplied function must fulfil ▪ Parameter performCalculation is of type: (parameter types) -> return type ▪ When calling: ▪ Supply a function as lambda expression that matches the parameter ▪ Return type is inferred automatically if not Unit (= void in Java) Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 64 private fun testFunctionParameters(performCalculation: (Int, Int) -> Int) { Log.d("Tests", "Calculation result: " + performCalculation(1, 2)) } testFunctionParameters( {a : Int, b : Int -> a + b } )
  65. 65. Adapter with Click Listener ▪ 1. Add 2nd parameter to PartAdapter constructor ▪ Function parameter ▪ Reqiures PartData as parameter, no value is returned (“Unit”) Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 65 class PartAdapter (val partItemList: List<PartData>, val clickListener: (PartData) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
  66. 66. View Holder with Click Listener ▪ 2. Assign click listener in PartViewHolder ▪ Assigned to the whole view, not just a Button / TextView / … ▪ Supply click listener as 2nd parameter of bind() function Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 66 class PartViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(part: PartData, clickListener: (PartData) -> Unit) { itemView.tv_part_item_name.text = part.itemName itemView.tv_part_id.text = part.id.toString() itemView.setOnClickListener { clickListener(part)} } }
  67. 67. Assign Click Listener ▪ 3. When Adapter binds ViewHolder, assign click listener ▪ clickListener part of constructor in PartAdapter ▪ -> automatically available as property in the PartAdapter class Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 67 override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { // Populate ViewHolder with data that corresponds to the position in the list // which we are told to load (holder as PartViewHolder).bind(partItemList[position], clickListener) }
  68. 68. Handle Clicks in MainActivity ▪ 4. Write function in MainActivity to handle clicked items ▪ 5. Extend construction of PartAdapter, supply function parameter Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 68 private fun partItemClicked(partItem : PartData) { Toast.makeText(this, "Clicked: ${partItem.itemName}", Toast.LENGTH_LONG).show() } rv_parts.adapter = PartAdapter(testData, { partItem : PartData -> partItemClicked(partItem) })
  69. 69. Final Test! Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 69
  70. 70. Exercise: Detail Page ▪ Create a DetailActivity ▪ Shows part details ▪ Extend click handler in MainActivity ▪ Launch second activity ▪ Pass data via Intent Extras Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 70
  71. 71. THANK YOU! Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 71

×