Advertisement
tuomasvaltanen

Untitled

Feb 1st, 2023 (edited)
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.94 KB | None | 0 0
  1. // Edistynyt mobiiliohjelmointi, 1.2.2023, luentomuistiinpanot
  2.  
  3. ApiFragment, ulkoasu:
  4.  
  5. <?xml version="1.0" encoding="utf-8"?>
  6. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  7. xmlns:tools="http://schemas.android.com/tools"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. android:orientation="vertical"
  11. tools:context=".ApiFragment">
  12. <Button
  13. android:id="@+id/button_get_comments"
  14. android:layout_width="match_parent"
  15. android:layout_height="wrap_content"
  16. android:text="GET COMMENTS" />
  17. </LinearLayout>
  18.  
  19.  
  20. // Comment-API
  21. // JSON URL = https://jsonplaceholder.typicode.com/comments
  22.  
  23.  
  24. // muista lisätä dependencyt ja permissionit manifestiin, ks. Moodle
  25. // ApiFragment:
  26.  
  27. class ApiFragment : Fragment() {
  28. private var _binding: FragmentApiBinding? = null
  29.  
  30. // This property is only valid between onCreateView and
  31. // onDestroyView.
  32. private val binding get() = _binding!!
  33. override fun onCreateView(
  34. inflater: LayoutInflater,
  35. container: ViewGroup?,
  36. savedInstanceState: Bundle?
  37. ): View? {
  38. _binding = FragmentApiBinding.inflate(inflater, container, false)
  39. val root: View = binding.root
  40. // print out the given parameter into logs
  41.  
  42. // haetaan dataa omalla funktiolla kun nappia painetaan
  43. binding.buttonGetComments.setOnClickListener {
  44. getComments()
  45. }
  46.  
  47. return root
  48. }
  49.  
  50. fun getComments()
  51. {
  52. // this is the url where we want to get our data from
  53. val JSON_URL = "https://jsonplaceholder.typicode.com/comments"
  54.  
  55. // Request a string response from the provided URL.
  56. val stringRequest: StringRequest = object : StringRequest(
  57. Request.Method.GET, JSON_URL,
  58. Response.Listener { response ->
  59.  
  60. // print the response as a whole
  61. // we can use GSON to modify this response into something more usable
  62. Log.d("ADVTECH", response)
  63.  
  64. },
  65. Response.ErrorListener {
  66. // typically this is a connection error
  67. Log.d("ADVTECH", it.toString())
  68. })
  69. {
  70. @Throws(AuthFailureError::class)
  71. override fun getHeaders(): Map<String, String> {
  72.  
  73. // basic headers for the data
  74. val headers = HashMap<String, String>()
  75. headers["Accept"] = "application/json"
  76. headers["Content-Type"] = "application/json; charset=utf-8"
  77. return headers
  78. }
  79. }
  80.  
  81. // Add the request to the RequestQueue. This has to be done in both getting and sending new data.
  82. // if using this in an activity, use "this" instead of "context"
  83. val requestQueue = Volley.newRequestQueue(context)
  84. requestQueue.add(stringRequest)
  85. }
  86.  
  87. override fun onDestroyView() {
  88. super.onDestroyView()
  89. _binding = null
  90. }
  91. }
  92.  
  93.  
  94. // Tarvitaan kommenttidatalle oma dataluokka, esim. Comment.kt:
  95. // tämän voi generoida json2kt.com -työkalulla
  96.  
  97. import com.google.gson.annotations.SerializedName
  98.  
  99.  
  100. data class Comment (
  101.  
  102. @SerializedName("postId" ) var postId : Int? = null,
  103. @SerializedName("id" ) var id : Int? = null,
  104. @SerializedName("name" ) var name : String? = null,
  105. @SerializedName("email" ) var email : String? = null,
  106. @SerializedName("body" ) var body : String? = null
  107.  
  108. )
  109.  
  110. // GSONin avulla JSON voidaan muuttaa Kotlin-muotoon
  111.  
  112. fun getComments()
  113. {
  114. // this is the url where we want to get our data from
  115. val JSON_URL = "https://jsonplaceholder.typicode.com/comments"
  116.  
  117. // alustetaan GSON
  118. val gson = GsonBuilder().setPrettyPrinting().create()
  119.  
  120. // Request a string response from the provided URL.
  121. val stringRequest: StringRequest = object : StringRequest(
  122. Request.Method.GET, JSON_URL,
  123. Response.Listener { response ->
  124.  
  125. // muutetaan raaka-JSON rajapinnasta (response) GSONin avulla listaksi Comment-objekteja
  126. var rows : List<Comment> = gson.fromJson(response, Array<Comment>::class.java).toList()
  127.  
  128. // tulostetaan silmukassa jokaisen kommentin email-osoite
  129. for(item in rows)
  130. {
  131. Log.d("ADVTECH", item.email.toString())
  132. }
  133.  
  134. },
  135. Response.ErrorListener {
  136. // typically this is a connection error
  137. Log.d("ADVTECH", it.toString())
  138. })
  139. {
  140. @Throws(AuthFailureError::class)
  141. override fun getHeaders(): Map<String, String> {
  142.  
  143. // basic headers for the data
  144. val headers = HashMap<String, String>()
  145. headers["Accept"] = "application/json"
  146. headers["Content-Type"] = "application/json; charset=utf-8"
  147. return headers
  148. }
  149. }
  150.  
  151. // Add the request to the RequestQueue. This has to be done in both getting and sending new data.
  152. // if using this in an activity, use "this" instead of "context"
  153. val requestQueue = Volley.newRequestQueue(context)
  154. requestQueue.add(stringRequest)
  155. }
  156.  
  157.  
  158. // RecyclerViewiä varten tarvitaan oma xml-tiedosto, joka esittää YKSITTÄISTÄ kommenttia listassa
  159.  
  160. <?xml version="1.0" encoding="utf-8"?>
  161. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  162. xmlns:app="http://schemas.android.com/apk/res-auto"
  163. xmlns:tools="http://schemas.android.com/tools"
  164. android:layout_width="match_parent"
  165. android:layout_height="140dp">
  166.  
  167. <TextView
  168. android:id="@+id/textView_comment_name"
  169. android:layout_width="wrap_content"
  170. android:layout_height="wrap_content"
  171. android:layout_margin="10dp"
  172. android:text="Kommentin name"
  173. android:textColor="#619526"
  174. android:textStyle="bold"
  175. app:layout_constraintStart_toStartOf="parent"
  176. app:layout_constraintTop_toTopOf="parent" />
  177.  
  178. <TextView
  179. android:id="@+id/textView_comment_email"
  180. android:layout_width="wrap_content"
  181. android:layout_height="wrap_content"
  182. android:layout_margin="10dp"
  183. android:text="Kommentin email"
  184. android:textColor="#6A33DA"
  185. android:textStyle="bold|italic"
  186. app:layout_constraintEnd_toEndOf="parent"
  187. app:layout_constraintTop_toTopOf="parent" />
  188.  
  189. <TextView
  190. android:id="@+id/textView_comment_body"
  191. android:layout_width="wrap_content"
  192. android:layout_height="wrap_content"
  193. android:layout_margin="10dp"
  194. android:text="Kommentin body"
  195. app:layout_constraintStart_toStartOf="parent"
  196. app:layout_constraintTop_toBottomOf="@+id/textView_comment_name" />
  197. </androidx.constraintlayout.widget.ConstraintLayout>
  198.  
  199.  
  200. // RecyclerView vaatii aina adapterin, jossa oma data kytketään omaan ulkoasuun
  201.  
  202. class CommentAdapter(private val comments: List<Comment>) : RecyclerView.Adapter<CommentAdapter.CommentHolder>() {
  203. // binding layerin muuttujien alustaminen
  204. private var _binding: RecyclerviewItemRowBinding? = null
  205. private val binding get() = _binding!!
  206.  
  207. // ViewHolderin onCreate-metodi. käytännössä tässä kytketään binding layer
  208. // osaksi CommentHolder-luokkaan (adapterin sisäinen luokka)
  209. // koska CommentAdapter pohjautuu RecyclerViewin perusadapteriin, täytyy tästä
  210. // luokasta löytyä metodi nimeltä onCreateViewHolder
  211. override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CommentHolder {
  212. // binding layerina toimii yksitätinen recyclerview_item_row.xml -instanssi
  213. _binding = RecyclerviewItemRowBinding.inflate(LayoutInflater.from(parent.context), parent, false)
  214. return CommentHolder(binding)
  215. }
  216.  
  217. // tämä metodi kytkee yksittäisen Comment-objektin yksittäisen CommentHolder-instanssiin
  218. // koska CommentAdapter pohjautuu RecyclerViewin perusadapteriin, täytyy tästä
  219. // luokasta löytyä metodi nimeltä onBindViewHolder
  220. override fun onBindViewHolder(holder: CommentHolder, position: Int) {
  221. val itemComment = comments[position]
  222. holder.bindComment(itemComment)
  223. }
  224.  
  225. // Adapterin täytyy pysty tietämään sisältämänsä datan koko tämän metodin avulla
  226. // koska CommentAdapter pohjautuu RecyclerViewin perusadapteriin, täytyy tästä
  227. // luokasta löytyä metodi nimeltä getItemCount
  228. override fun getItemCount(): Int {
  229. return comments.size
  230. }
  231.  
  232. // CommentHolder, joka määritettiin oman CommentAdapterin perusmäärityksessä (ks. luokan yläosa)
  233. // Holder-luokka sisältää logiikan, jolla data ja ulkoasu kytketään toisiinsa
  234. class CommentHolder(v: RecyclerviewItemRowBinding) : RecyclerView.ViewHolder(v.root), View.OnClickListener {
  235.  
  236. // tämän kommentin ulkoasu ja varsinainen data
  237. private var view: RecyclerviewItemRowBinding = v
  238. private var comment: Comment? = null
  239.  
  240. // mahdollistetaan yksittäisen itemin klikkaaminen tässä luokassa
  241. init {
  242. v.root.setOnClickListener(this)
  243. }
  244.  
  245. // metodi, joka kytkee datan yksityiskohdat ulkoasun yksityiskohtiin
  246. fun bindComment(comment : Comment)
  247. {
  248. // otetaan kommentti talteen ylätasolle, että voimme käyttää sitä myös esim. onClickissä
  249. this.comment = comment
  250.  
  251. view.textViewCommentName.text = comment.name
  252. view.textViewCommentEmail.text = comment.email
  253. view.textViewCommentBody.text = comment.body
  254. }
  255.  
  256. // jos itemiä klikataan käyttöliittymässä, ajetaan tämä koodio
  257. override fun onClick(v: View) {
  258. Log.d("ADVTECH", "RecyclerView CLICK!!!")
  259. }
  260. }
  261. }
  262.  
  263. // lisätään ApiFragmentin ulkoasuun myös RecyclerView (huomaa recyclerviewin id myös)
  264.  
  265. <?xml version="1.0" encoding="utf-8"?>
  266. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  267. xmlns:tools="http://schemas.android.com/tools"
  268. android:layout_width="match_parent"
  269. android:layout_height="match_parent"
  270. android:orientation="vertical"
  271. tools:context=".ApiFragment">
  272. <Button
  273. android:id="@+id/button_get_comments"
  274. android:layout_width="match_parent"
  275. android:layout_height="wrap_content"
  276. android:text="GET COMMENTS" />
  277.  
  278. <androidx.recyclerview.widget.RecyclerView
  279. android:id="@+id/recyclerView_comments"
  280. android:layout_width="match_parent"
  281. android:layout_height="match_parent" />
  282. </LinearLayout>
  283.  
  284. // tehdään loput kytkennät recyclerviewiin fragmentissa
  285.  
  286. class ApiFragment : Fragment() {
  287. private var _binding: FragmentApiBinding? = null
  288.  
  289. // alustetaan viittaus adapteriin sekä luodaan LinearLayoutManager
  290. // RecyclerView tarvitsee jonkin LayoutManagerin, joista yksinkertaisin on Linear
  291. private lateinit var adapter: CommentAdapter
  292. private lateinit var linearLayoutManager: LinearLayoutManager
  293.  
  294. // This property is only valid between onCreateView and
  295. // onDestroyView.
  296. private val binding get() = _binding!!
  297. override fun onCreateView(
  298. inflater: LayoutInflater,
  299. container: ViewGroup?,
  300. savedInstanceState: Bundle?
  301. ): View? {
  302. _binding = FragmentApiBinding.inflate(inflater, container, false)
  303. val root: View = binding.root
  304.  
  305. // luodaan layout manager ja kytketään se ulkoasun recyclerviewiin
  306. linearLayoutManager = LinearLayoutManager(context)
  307. binding.recyclerViewComments.layoutManager = linearLayoutManager
  308.  
  309. // haetaan dataa omalla funktiolla kun nappia painetaan
  310. binding.buttonGetComments.setOnClickListener {
  311. getComments()
  312. }
  313.  
  314. return root
  315. }
  316.  
  317. fun getComments()
  318. {
  319. // this is the url where we want to get our data from
  320. val JSON_URL = "https://jsonplaceholder.typicode.com/comments"
  321.  
  322. // alustetaan GSON
  323. val gson = GsonBuilder().setPrettyPrinting().create()
  324.  
  325. // Request a string response from the provided URL.
  326. val stringRequest: StringRequest = object : StringRequest(
  327. Request.Method.GET, JSON_URL,
  328. Response.Listener { response ->
  329.  
  330. // muutetaan raaka-JSON rajapinnasta (response) GSONin avulla listaksi Comment-objekteja
  331. var rows : List<Comment> = gson.fromJson(response, Array<Comment>::class.java).toList()
  332.  
  333. // tulostetaan silmukassa jokaisen kommentin email-osoite
  334. for(item in rows)
  335. {
  336. Log.d("ADVTECH", item.email.toString())
  337. }
  338.  
  339. // luodaan adapteri datan kanssa ja kytketään se recycler viewiin
  340. adapter = CommentAdapter(rows)
  341. binding.recyclerViewComments.adapter = adapter
  342.  
  343. },
  344. Response.ErrorListener {
  345. // typically this is a connection error
  346. Log.d("ADVTECH", it.toString())
  347. })
  348. {
  349. @Throws(AuthFailureError::class)
  350. override fun getHeaders(): Map<String, String> {
  351.  
  352. // basic headers for the data
  353. val headers = HashMap<String, String>()
  354. headers["Accept"] = "application/json"
  355. headers["Content-Type"] = "application/json; charset=utf-8"
  356. return headers
  357. }
  358. }
  359.  
  360. // Add the request to the RequestQueue. This has to be done in both getting and sending new data.
  361. // if using this in an activity, use "this" instead of "context"
  362. val requestQueue = Volley.newRequestQueue(context)
  363. requestQueue.add(stringRequest)
  364. }
  365.  
  366. override fun onDestroyView() {
  367. super.onDestroyView()
  368. _binding = null
  369. }
  370. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement