Android Development with Kotlin, Part 2 - Internet Services and JSON
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. 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. 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
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. 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. 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. 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. 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. ANDROID MENUS
User Interaction, in a different way
Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 10
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. 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. 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. 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. 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. WEB SERVICE CLIENT
REST & More – access URLs
Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 16
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. 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. 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. 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. 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. THREADS AND MULTITASKING
Keeping the UI responsive
Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 22
24. Single User Interface Thread
Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 24
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. 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. 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. 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. 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. 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. 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. 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. 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)
}
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. 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"/>
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. Exercise
▪ Repetition: save state of TextView to survive screen rotation!
Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 39
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. 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
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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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)
60. RECYCLERVIEW & CLICK HANDLING
Advanced Topics for the Pros
Android Development with Kotlin, Part 2 | 2018 | Andreas Jakl | FH St. Pölten 60
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. 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. 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. 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. 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. 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. 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. 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) })
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