„Kliensalkalmazások” változatai közötti eltérés

A VIK Wikiből
a →‎Vizsga: Címsorok rendezése
Órák anyagának és segédanyagoknak a hozzáadása
68. sor: 68. sor:
***Arrow functionöket <code>const</code>-tal érdemes definiálni, mivel általában nem változik a tartalmuk.
***Arrow functionöket <code>const</code>-tal érdemes definiálni, mivel általában nem változik a tartalmuk.
***Az ''Objektum nem adható vissza simán'' pontban szándékosan hibás változódeklarációk szerepelnek.
***Az ''Objektum nem adható vissza simán'' pontban szándékosan hibás változódeklarációk szerepelnek.
*[[Média:Kliens ea4 2023 web.pdf|5. hét (Albert István)]]: TypeScript: transpiler, static typing (<code>any</code>, <code>noImplicitAny</code>), structural typing, deklaráció (<code>var</code>, <code>let</code>, <code>const</code>), <code>null</code> (<code>strictNullChecks</code>), <code>undefined</code>, type narrowing / assertion, non-null assertion, optional chaining, null coalescing, enum (sorszámozás), string / number literal (union), type annotation / alias, optional values, <code>interface</code>; <code>class</code>: <code>static</code>, constructor, <code>readonly</code>, <code>protected</code>, <code>extends</code>, <code>super</code>, <code>private</code>, erősen védett mező; method overload (signatures), generic types, típuskényszer, metszettípus, spread, dekorátorok; modulok: <code>export</code>, <code>import</code>, típusdeklarációs fájl (<code>.d.ts</code>)
*[[Média:Kliens ea4 2023 web.pdf|5. hét (Albert István)]]: TypeScript: transpiler, static typing (<code>any</code>, <code>noImplicitAny</code>), structural typing, deklaráció (<code>var</code>, <code>let</code>, <code>const</code>), <code>null</code> (<code>strictNullChecks</code>), <code>undefined</code>, type narrowing / assertion, non-null assertion, optional chaining, null coalescing, enum (sorszámozás), string / number literal (union), type annotation / alias, optional values, <code>interface</code>; <code>class</code>: <code>static</code>, constructor, <code>readonly</code>, <code>protected</code>, <code>extends</code>, <code>super</code>, <code>private</code>, erősen védett mező; [https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads function overload] signatures, generic types, típuskényszer, metszettípus, spread, dekorátorok; modulok: <code>export</code>, <code>import</code>, típusdeklarációs fájl (<code>.d.ts</code>)
**Az 52. dián az utolsó szöveges bekezdés pontosabban: ''míg a JavaScript tetszőleges típuson, a TypeScript csak <code>number</code>-ön tud <code>toString</code>-et hívni''.
**Az 52. dián az utolsó szöveges bekezdés pontosabban: ''míg a JavaScript tetszőleges típuson, a TypeScript csak <code>number</code>-ön tud <code>toString</code>-et hívni''.
*[[Média:Kliens ea5 2023 web.pdf|6. hét (Albert István)]]: Angular: MV*, architektúra, metaadatok, dekorátorok, komponensek, szolgáltatások, Component, string interpolation, adatkötés (@Input / @Output, CSS class / -stílus), események kötése, kétirányú adatkötés, attribútum / property, (strukturális / attribútum)direktívák (HostListener), ngIf, ngFor, direktíva, alkalmazás- / komponens-életciklus, lifecycle hooks, ngOnInit, ngOnChanges, SimpleChange, ngDoCheck
*[[Média:Kliens ea5 2023 web.pdf|6. hét (Albert István)]]: Angular: MV*, architektúra, metaadatok, dekorátorok, komponensek, szolgáltatások, Component, string interpolation, adatkötés (@Input / @Output, CSS class / -stílus), események kötése, kétirányú adatkötés, attribútum / property, (strukturális / attribútum)direktívák (HostListener), ngIf, ngFor, direktíva, alkalmazás- / komponens-életciklus, lifecycle hooks, ngOnInit, ngOnChanges, SimpleChange, ngDoCheck
76. sor: 76. sor:
====Android====  
====Android====  
*8. hét: ''szünet''
*8. hét: ''szünet''
*[[Média:Kliens ea 09 20240408.pdf|9. hét (Gazdi László)]]: alapok, Java, XML alapú UI, eseménykezelés, Kotlin; '''<code>Activity</code>, <code>Service</code>, content provider, <code>BroadcastReceiver</code>;''' manifest, erőforrások; compiler (Dalvik bytecode), <code>.apk</code>; '''activity lifecycle''' (callback függvények, állapot mentése, váltás)
*[[Média:Kliens ea 09 20240408.pdf|9. hét (Gazdi László)]]: alapok, Java; View (XML): <code>TextView</code>; eseménykezelés, Kotlin; '''<code>Activity</code>, <code>Service</code>, content provider, <code>BroadcastReceiver</code>;''' manifest, erőforrások; <code>.dex</code> compiler (Dalvik bytecode), <code>.apk</code>; '''activity lifecycle''' (callback függvények, állapot mentése, váltás)
**Megjegyzések a 16. diához:
**Megjegyzések a 16. diához:
***Az OS X már 2016 óta macOS.
***Az OS X már 2016 óta macOS.
83. sor: 83. sor:
*[[Média:Kliens ea 10 20240415.pdf|10. hét (Gazdi László)]]: '''<code>Activity</code>''': back stack, vezérlés; <code>Intent</code>: típusai, részei, explicit / implicit, extras, képességek, filter; <code>startActivityForResult()</code>, <code>onActivityResult()</code>; erőforrások (i18n); UI: <code>viewBinding</code>; dpi, dp, sp; <code>LinearLayout</code>, <code>RelativeLayout</code>, <code>ConstraintLayout</code>; padding és margin
*[[Média:Kliens ea 10 20240415.pdf|10. hét (Gazdi László)]]: '''<code>Activity</code>''': back stack, vezérlés; <code>Intent</code>: típusai, részei, explicit / implicit, extras, képességek, filter; <code>startActivityForResult()</code>, <code>onActivityResult()</code>; erőforrások (i18n); UI: <code>viewBinding</code>; dpi, dp, sp; <code>LinearLayout</code>, <code>RelativeLayout</code>, <code>ConstraintLayout</code>; padding és margin
*[[Média:Kliens ea 11 20240422.pdf|11. hét (Pásztor Dániel)]]: <code>View</code>: <code>getLayoutInflater()</code>, validáció, <code>Menu</code>, <code>ActionBar</code>, <code>Toolbar</code>; <code>PopupWindow</code>, <code>AlertDialog</code>, <code>Snackbar</code>; <code>style</code>, <code>Theme</code>; grafikák, animációk
*[[Média:Kliens ea 11 20240422.pdf|11. hét (Pásztor Dániel)]]: <code>View</code>: <code>getLayoutInflater()</code>, validáció, <code>Menu</code>, <code>ActionBar</code>, <code>Toolbar</code>; <code>PopupWindow</code>, <code>AlertDialog</code>, <code>Snackbar</code>; <code>style</code>, <code>Theme</code>; grafikák, animációk
**Habár a diasoron én nem láttam példát az <code>ImageView</code> használatára, [[Kliensalkalmazások#:~:text=Vázolja fel a képen látható nézet kódját a View framework segítségével!|a vizsgán kérdezik]]. De legalább az egyik laboron [https://bmeviaubb03.github.io/laborok/laborok/android/ui-basics/#:~:text=A%20m%C3%A1sik%20%C3%BAjdons%C3%A1g%20itt%20az%20ImageView%20haszn%C3%A1lata. szó esik róla].
*[[Média:Kliens ea 12 20240429.pdf|12. hét (Gazdi László)]]: <code>Fragment</code>: életciklus, csatolása (statikusan és dinamikusan), <code>FragmentManager</code>, <code>FragmentTransaction</code>, kommunikáció, <code>DialogFragment</code>; <code>navigation</code>: component, graph; <code>RecyclerView</code>: <code>ViewHolder</code>, <code>Adapter</code>; perzisztens adattárolás: <code>(Shared)Preferences</code>, SQLite, ORM, <code>room</code>, javasolt architektúra; fájlkezelés: internal / external storage, statikus fájlok, nyilvános lemezterület; BaaS: Firebase; '''content provider:''' elérése (<code>CONTENT_URI</code>), műveletek, engedélyek, <code>Cursor</code>, <code>ContentResolver</code>, CRUD
*[[Média:Kliens ea 12 20240429.pdf|12. hét (Gazdi László)]]: <code>Fragment</code>: életciklus, csatolása (statikusan és dinamikusan), <code>FragmentManager</code>, <code>FragmentTransaction</code>, kommunikáció, <code>DialogFragment</code>; <code>navigation</code>: component, graph; <code>RecyclerView</code>: <code>ViewHolder</code>, <code>Adapter</code>; perzisztens adattárolás: <code>(Shared)Preferences</code>, SQLite, ORM, <code>room</code>, javasolt architektúra; fájlkezelés: internal / external storage, statikus fájlok, nyilvános lemezterület; BaaS: Firebase; '''content provider:''' elérése (<code>CONTENT_URI</code>), műveletek, engedélyek, <code>Cursor</code>, <code>ContentResolver</code>, CRUD
**Megjegyzés az 51. diához: a <code>BLOB</code> is egy támogatott adattípus.
**Megjegyzés az 51. diához: a <code>BLOB</code> is egy támogatott adattípus.
*[[Média:Kliens ea 13 20240506.pdf|13. hét (Gazdi László)]]: Jetpack Compose: <code>@Composable</code> '''(5 szabálya),''' <code>@Preview</code>, layoutok (<code>Column</code>, <code>Row</code>, <code>Box</code>), weight, <code>Alignment</code> és <code>Arrangement</code>, <code>Modifier</code>, <code>Scaffold</code>, <code>TextField</code>, Material Design; mappastruktúra, composition / initial composition / recomposition, adatok átadása; <code>ViewModel</code>: MVVM, MVI; navigation graph: funkciók, paraméterek, konstansok; dialógusok: <code>AlertDialog</code>; listák: lazy loading; szálak és coroutine-ok: suspending functions; flow
*[[Média:Kliens ea 13 20240506.pdf|13. hét (Gazdi László)]]: Jetpack Compose: <code>@Composable</code> '''(5 szabálya),''' <code>@Preview</code>, layoutok (<code>Column</code>, <code>Row</code>, <code>Box</code>), weight, <code>Alignment</code> és <code>Arrangement</code>, <code>Modifier</code>, <code>Scaffold</code>, <code>TextField</code>, Material Design; mappastruktúra, composition / initial composition / recomposition, adatok átadása; <code>ViewModel</code>: MVVM, MVI; navigation graph: funkciók, paraméterek, konstansok; dialógusok: <code>AlertDialog</code>; listák: lazy loading; szálak és coroutine-ok: suspending functions; flow
*[[Média:Kliens ea 14 20240513.pdf|14. hét (Gazdi László)]]: hálózati kommunikáció: near-field: NFC, Bluetooth (LE), [https://developers.google.com/nearby/ Nearby]; web: TCP/IP socket (<code>InputStream</code>, <code>OutputStream</code>), UDP (Kyronet); HTTP(S): kapcsolatok kezelése, könyvtárak, timeout; aszinkron kommunikáció; adatformátumok: JSON, XML; REST: Retrofit (entitások, API); <code>'''BroadcastReceiver'''</code>: események, intentek (<code>BOOT_COMPLETED</code>); '''<code>Service</code>''': készítése, (működési) típusok, limitációk, megvalósítás, életciklusmodell, kezelés, műveletek végrehajtása; runtime permissions: típusai, kezelése (kérés), best practice, Jetpack Compose
*[[Média:Kliens ea 14 20240513.pdf|14. hét (Gazdi László)]]: hálózati kommunikáció: near-field: NFC, Bluetooth (LE), [https://developers.google.com/nearby/ Nearby]; web: TCP/IP socket (<code>InputStream</code>, <code>OutputStream</code>), UDP (Kyronet); HTTP(S): kapcsolatok kezelése, könyvtárak, timeout; aszinkron kommunikáció; adatformátumok: JSON, XML; REST: Retrofit (entitások, API); <code>'''BroadcastReceiver'''</code>: események, intentek (<code>BOOT_COMPLETED</code>); '''<code>Service</code>''': készítése, (működési) típusok, limitációk, megvalósítás, életciklusmodell, kezelés, műveletek végrehajtása; runtime permissions: típusai, kezelése (kérés), best practice, Jetpack Compose
**Megjegyzés a 14. diához: a Nearby Messages [https://developers.google.com/nearby/#:~:text=Nearby%20Messages%20is%20deprecated%20and%20will%20stop%20working%20as%20of%20December%202023. 2023], a Nearby Notifications pedig már [https://developers.google.com/nearby/notifications/overview#:~:text=Android%20users%20will%20stop%20receiving%20Nearby%20Notifications%20on%20December%206th,%202018. 2018 decemberében] meg lett szüntetve.
**Megjegyzés a 14. diához: a Nearby Messagest [https://developers.google.com/nearby/#:~:text=Nearby%20Messages%20is%20deprecated%20and%20will%20stop%20working%20as%20of%20December%202023. 2023], a Nearby Notifications-t pedig már [https://developers.google.com/nearby/notifications/overview#:~:text=Android%20users%20will%20stop%20receiving%20Nearby%20Notifications%20on%20December%206th,%202018. 2018 decemberében] megszüntették.
*15. hét: ''szünet''
*15. hét: ''szünet''


136. sor: 137. sor:
==== 2024. tavasz ====
==== 2024. tavasz ====


*Vizsga
*A vizsga kifejtős kérdései
**''Mire való a <code>[https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById getElementById]</code> függvény? Hogyan lehet elérni?'' (kifejtős)
**''Mik az overload szignatúrák? Hogyan kell őket használni?''
***egy függvénynek többféle számú és típusú bemeneti változóját lehet velük definiálni
***pl. az alábbi kód első két sorában:<syntaxhighlight lang="ts" line="1">
function makeDate(epoch: number): Date;
function makeDate(year: number, month: number, day: number): Date;
function makeDate(epochOrYear: number, month?: number, day?: number): Date {
  if (month !== undefined && day !== undefined) {
    return new Date(epochOrYear, month, day);
  } else {
    return new Date(epochOrYear);
  }
}
const dateFromEpoch = makeDate(1719082884);
const dateFromDate = makeDate(2024, 6, 22);
</syntaxhighlight>a 3. sorban található az implementációs szignatúra
****mindig csak egy lehet belőle
****nem lehet közvetlenül meghívni
**''Mire való a <code>[https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById getElementById]</code> függvény? Hogyan lehet elérni?''
***egy adott ID-jű elem DOM-ban való megtalálására
***egy adott ID-jű elem DOM-ban való megtalálására
****így könnyen lehet a JS-kódból módosítani a DOM-ot
****így könnyen lehet a JS-kódból módosítani a DOM-ot
157. sor: 175. sor:
disablerButton.addEventListener("click", disableButton("buttonToDisable"));
disablerButton.addEventListener("click", disableButton("buttonToDisable"));
</syntaxhighlight>
</syntaxhighlight>
**''Mi a különbség a'' block ''és'' inline ''típusú HTML-elemek között?'' (kifejtős)
**''Mi a különbség a'' block ''és'' inline ''típusú HTML-elemek között?''
***block
***block
****pl.: <code><nowiki><div></nowiki></code>, <code><nowiki><p></nowiki></code>
****pl.: <code><nowiki><div></nowiki></code>, <code><nowiki><p></nowiki></code>
166. sor: 184. sor:
****nem tölti ki a szülőjének teljes szélességét
****nem tölti ki a szülőjének teljes szélességét
****ugyanabban a sorban jelenik meg
****ugyanabban a sorban jelenik meg
*****így lehet formázni linkeket, vagy pl. highlightolni (kihúzni) szöveget
***** így lehet formázni linkeket, vagy pl. highlightolni (kihúzni) szöveget
*****csak a tagen belüli szövegre vonatkozik
*****csak a tagen belüli szövegre vonatkozik
**''Mire való egy <code>.d.ts</code> kiterjesztésű fájl?'' (kifejtős)
**''Mire valóak az űrlapok?''
**''Mire való egy űrlap elemeiben a <code>name</code> attribútum?''
***egyes beviteli mezők elnevezésére
****az űrlap beküldésekor a kliens ezeket használja a szervernek küldött adatok megnevezésére
*****GET esetén: <code><nowiki>https://foo.com/?name1=value1&name2=value2</nowiki></code>
*****POST esetén: a fenti, <code>?</code> utáni rész kerül a bodyba
***a JS-kódban a <code>document.getElementByName()</code> használatakor erre lehet hivatkozni
****ezzel könnyen manipulálható a DOM
**''Mire való egy <code>.d.ts</code> kiterjesztésű fájl?''
***declaration file
***declaration file
***kizárólag a hozzá tartozó JavaScript-fájl típusinformációit tartalmazza
***kizárólag a hozzá tartozó JavaScript-fájl típusinformációit tartalmazza
***gyakorlatilag ugyanaz, mint Pythonban a [https://typing.readthedocs.io/en/latest/source/stubs.html type stub], de a TypeScript fordításidőben jelzi a típusokkal kapcsolatos problémákat (Pythonban ezeket csak az IDE mutatja)
***gyakorlatilag ugyanaz, mint Pythonban a [https://typing.readthedocs.io/en/latest/source/stubs.html type stub], de a TypeScript fordításidőben jelzi a típusokkal kapcsolatos problémákat (Pythonban ezeket csak az IDE mutatja)
**''Mire szolgál az Angular <code>[https://angular.dev/api/common/NgIf?tab=description ngIf]</code> direktívája?'' (kifejtős)
**''Milyen előnyei vannak a dependency injection használatának?''
*** separation of concerns
**** az injektor a felelős a dependency létrehozásáért, életciklusáért
***** teljesen független a dependency életciklusa a komponensétől
****** újrafelhasználható
***** erősebb dekompozíció
****** jobb tesztelhetőség
***** a komponens kódja így rövidebb lesz
**** csak az injektornak kell ismernie a függőségi gráfot
**''Mire szolgál az Angular <code>[https://angular.dev/api/common/NgIf?tab=description ngIf]</code> direktívája?''
***elemek feltételes megjelenítésére
***elemek feltételes megjelenítésére
*** pl.:<syntaxhighlight lang="ng2" line="1">
***pl.:<syntaxhighlight lang="ng2" line="1">
<div *ngIf="train">
<div *ngIf="train">
     <p>
     <p>
190. sor: 225. sor:
===Android===
===Android===


==== 2024. tavasz ====
==== 2024. tavasz====
*A diasorokon szereplő kifejtős kérdések
*A diasorokon szereplő kifejtős kérdések
**9. hét
**9. hét
***Milyen lehetőségeink vannak a fejlesztés közbeni debugolásra?
***Milyen lehetőségeink vannak a fejlesztés közbeni debugolásra?
***Miket kell tartalmaznia a manifestnek?
***Miket kell tartalmaznia a manifestnek?
*** Mit értünk erőforrás-minősítő alatt?
***Mit értünk erőforrás-minősítő alatt?
*** Magyarázza el a fordítás mechanizmusát!
***Magyarázza el a fordítás mechanizmusát!
*** Mit jelent az obfuszkálás?
***Mit jelent az obfuszkálás?
***Az Activity callback életciklus-függvények felüldefiniálásakor meg kell-e hívni kötelezően az ősosztály implementációját? Miért?
***Az Activity callback életciklus-függvények felüldefiniálásakor meg kell-e hívni kötelezően az ősosztály implementációját? Miért?
***Ha <code>A</code> <code>Activity</code>-ről átváltunk a <code>B</code> <code>Activity</code>-re, milyen sorrendben hívódnak meg az életciklusfüggvények?
***Ha <code>A</code> <code>Activity</code>-ről átváltunk a <code>B</code> <code>Activity</code>-re, milyen sorrendben hívódnak meg az életciklus( callback )függvények?
**10. hét
****...
**10. hét  
***Magyarázza el az <code>Activity</code> back stack működési elvét!
***Magyarázza el az <code>Activity</code> back stack működési elvét!
***Hogyan kell egy <code>Activity</code>-t indítani, ha vissza akarunk kapni adatot tőle?
***Hogyan kell egy <code>Activity</code>-t indítani, ha vissza akarunk kapni adatot tőle?
***Hogyan működik az implicit <code>Intent</code>?
***Hogyan működik az implicit <code>Intent</code>?
*** Mit értünk ''sűrűségfüggetlen pixel'' alatt?
***Mit értünk ''sűrűségfüggetlen pixel'' alatt?
***Egy 320 dpi-s képernyőn <code>1.dp</code> hány darab pixelnek felel meg?
***Egy 320 dpi-s képernyőn <code>1.dp</code> hány darab pixelnek felel meg?
***Sorolja fel a legfontosabb androidos layoutokat!
***Sorolja fel a legfontosabb androidos layoutokat!
224. sor: 260. sor:
***Mire jó egy content provider?
***Mire jó egy content provider?
***Milyen formában adja vissza az adatokat egy content provider?
***Milyen formában adja vissza az adatokat egy content provider?
**13. hét  
**13. hét
***Mik a Jetpack Compose használatának előnyei?
***Mik a Jetpack Compose használatának előnyei?
***Milyen Jetpack Compose layoutokat ismer? Jellemezze őket!
***Milyen Jetpack Compose layoutokat ismer? Jellemezze őket!
233. sor: 269. sor:
***Mik azok a coroutine-ok?
***Mik azok a coroutine-ok?
***Mire való a flow, és hogyan használjuk?
***Mire való a flow, és hogyan használjuk?
**14. hét
** 14. hét
***Milyen rövidtávú kommunikációs technológiákat ismer?
***Milyen rövidtávú kommunikációs technológiákat ismer?
***Milyen hosszútávú kommunikációs technológiákat ismer?
***Milyen hosszútávú kommunikációs technológiákat ismer?
***Mi a különbség az UDP és a TCP/IP között?
***Mi a különbség az UDP és a TCP/IP között?
*** Hogyan kell végezni a hálózati kommunikációt?
***Hogyan kell végezni a hálózati kommunikációt?
***Mire szolgál a Retrofit library?
***Mire szolgál a Retrofit library?
***Milyen módszereket ismer a <code>BroadcastReceiver</code>-ek regisztrálására?
***Milyen módszereket ismer a <code>BroadcastReceiver</code>-ek regisztrálására?
*** Hogyan biztosítható, hogy egy bizonyos típusú broadcastot megkapjon a komponensünk?
***Hogyan biztosítható, hogy egy bizonyos típusú broadcastot megkapjon a komponensünk?
***Milyen típusú <code>Service</code>-eket ismer?
***Milyen típusú <code>Service</code>-eket ismer?
***Mire kell nagyon figyelni egy <code>Service</code> írásakor?
***Mire kell nagyon figyelni egy <code>Service</code> írásakor?
246. sor: 282. sor:
***Milyen fázisai vannak a veszélyes engedélyek kérésének?
***Milyen fázisai vannak a veszélyes engedélyek kérésének?
*Vizsga
*Vizsga
** ''Hogyan tudunk saját stílust definiálni? Hogyan tudjuk ezt a stílust az egész alkalmazásra érvényesíteni?'' (kifejtős)
**''Hogyan tudunk saját stílust definiálni? Hogyan tudjuk ezt a stílust az egész alkalmazásra érvényesíteni?'' (kifejtős)
***View
***View
****Saját stílust a <code>res/values/styles.xml</code> fájlban egy <code><style></code> tag, majd ez alatt további <code><item></code> tagek hozzáadásával lehet definiálni.
****Saját stílust a <code>res/values/styles.xml</code> fájlban egy <code><style></code> tag, majd ez alatt további <code><item></code> tagek hozzáadásával lehet definiálni.
253. sor: 289. sor:
****Saját stílust egy <code>@Composable</code> függvény (pl. <code>MyTheme</code>) létrehozásával lehet definiálni, melyben pl. a <code>MaterialTheme</code> függvényt az általunk választott paraméterekkel hívjuk meg.
****Saját stílust egy <code>@Composable</code> függvény (pl. <code>MyTheme</code>) létrehozásával lehet definiálni, melyben pl. a <code>MaterialTheme</code> függvényt az általunk választott paraméterekkel hívjuk meg.
****A <code>MainActivity</code> class <code>setContent</code> függvényében az <code>App</code> függvény hívását a <code>MyTheme</code> függvény hívásába kell ágyazni.
****A <code>MainActivity</code> class <code>setContent</code> függvényében az <code>App</code> függvény hívását a <code>MyTheme</code> függvény hívásába kell ágyazni.
**''Mi a Fragment?'' (kifejtős)
***objektumok, melyek...
****a képernyő egy nagyobb részéért felelősek
*****résznézeteket írnak le
*****Activity-kbe lehet őket ágyazni
******egyszerre többet is
***** növelni lehet velük a modularitást
****és / vagy a háttérben munkát végeznek
**''Mire és hogyan használható egy flow?'' (kifejtős)  
**''Mire és hogyan használható egy flow?'' (kifejtős)  
***A flow egy Python generatorhoz vagy egy Java Streamhez hasonló változótípus.
***A flow egy Python generatorhoz vagy egy Java Streamhez hasonló változótípus.
259. sor: 303. sor:
***Segítségével pl. fel lehet iratkozni egy adatfolyamra, hogy onnan folyamatosan kapjunk frissítéseket.
***Segítségével pl. fel lehet iratkozni egy adatfolyamra, hogy onnan folyamatosan kapjunk frissítéseket.
***A <code>Flow<></code> típusú változó <code>.collect { }</code> függvényét meghívva egy lambda kifejezést lehet végrehajtani a kapott értékkel.
***A <code>Flow<></code> típusú változó <code>.collect { }</code> függvényét meghívva egy lambda kifejezést lehet végrehajtani a kapott értékkel.
** ''Vázolja fel a képen látható nézet kódját Jetpack Compose segítségével! A kódnak nem kell tökéletesnek és teljesnek lennie, de a lényegi részek szerepeljenek benne.'' (kódolós) A képen egy képernyő, melynek közepén teljes szélességben egy ''Email'' feliratú szövegmező látható, alatta egy ''Password'' feliratúval. Mindkét szövegmezőbe ugyanazon látható szöveg van beírva. Alattuk pedig egy ''Login'' gomb látható, szintén a képernyő teljes szélességében.
**''Vázolja fel a képen látható nézet kódját '''Jetpack Compose''' segítségével! A kódnak nem kell tökéletesnek és teljesnek lennie, de a lényegi részek szerepeljenek benne.'' A képen egy képernyő, melynek közepén teljes szélességben egy ''Email'' feliratú szövegmező látható, alatta egy ''Password'' feliratúval. Mindkét szövegmezőbe ugyanazon látható szöveg van beírva. Alattuk pedig egy ''Login'' gomb látható, szintén a képernyő teljes szélességében.
***<syntaxhighlight lang="kotlin" line="1">
***<syntaxhighlight lang="kotlin" line="1">
@Composable
@Composable
284. sor: 328. sor:
     }
     }
}
}
</syntaxhighlight>  
</syntaxhighlight>
***''Vázolja fel a képen látható nézet kódját a '''View''' framework segítségével! A kódnak nem kell tökéletesnek és teljesnek lennie, de a lényegi részek szerepeljenek benne.''[[Fájl:Kliens vizsga3 20240617 the-lord-of-the-rings.svg|keret|keretnélküli|332x332px]]
****<syntaxhighlight lang="xml" line="1">
<RelativeLayout
    android:background="#000000">
   
    <ImageView
        android:src="@drawable/one_ring_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:padding="16dp" />
   
    <LinearLayout
        android:layout_toEndOf="@id/one_ring_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_centerVertical="true"
        android:background="#FFFFFF">
       
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="J. R. R. Tolkien"
            android:textColor="#000000"
            android:textSize="24sp"
            android:layout_marginBottom="8dp" />
       
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="The Lord of the Rings"
            android:textColor="#000000"
            android:textSize="24sp" />
       
    </LinearLayout>
 
</RelativeLayout>
</syntaxhighlight>
{{Lábléc_-_Üzemmérnök-informatikus_alapszak}}
{{Lábléc_-_Üzemmérnök-informatikus_alapszak}}

A lap 2024. június 22., 20:53-kori változata

Kliensalkalmazások
Tárgykód
VIAUBB03
Általános infók
Szak
üzemmérnök
Kredit
5
Ajánlott félév
4
Tanszék
AUT
Követelmények
Labor
13 db
KisZH
nincs
NagyZH
nincs
Házi feladat
2 db
Vizsga
írásbeli
Elérhetőségek

A tárgy célja, hogy a hallgatók megismerjék a kliensoldali alkalmazások fejlesztésének módszereit és meghatározó technológiáit különös tekintettel a vékony kliensekre (webes és mobil kliensek). A tárgy külön figyelmet fordít arra, hogy a technológiai lehetőségeken túl a hallgatók gyakorlati problémákkal és megoldásokkal is találkozzanak a félév során.

Követelmények

A szorgalmi időszakban

Laborgyakorlatok

  • Az összesen 10 laborból legalább 3 illetve 5 teljesítése a két témakörben.
  • A laborfeladatok felöltésének határideje: 1 hét.

Házi feladat

A tárgyhoz 2 házi feladat (részteljesítmény értékelés) tartozik, mobilos és webes témakörben. Az első feladat bemutatásának határideje a 6. heti, a másodiké a 14. heti laboralkalom. Az első házi feladatra 10, a másodikra 20 pont kapható, amelyeknek egyenként 50%-át el kell érni.

Aláírás

Mindkét házi feladat sikeres bemutatása és legalább 5 és 10 pont elérése. Legalább 8 (3+5) labor sikeres teljesítése.

Pótlási lehetőség

A póthéten az egyik házi feladat pótolható.

Vizsga

A vizsgaidőszakban írásbeli vizsgát tartunk, amely 60 pontos (36 pont web + 24 pont Android), ebből legalább 30 pontot el kell érni a sikerességhez. Igaz-hamis, feleletválasztós, kifejtős és kódolós kérdések is várhatóak.

Osztályozás

A végső osztályzatot a házi és a vizsga pontszámok összeadásával határozzuk meg.

Laborok: max. 10 pont Mobil házi feladat: max. 10 pont Webes házi feladat: max. 20 pont Vizsga: max. 60 pont

Értékelés

  • 88– 100: jeles
  • 75 – 87: jó
  • 62 – 74: közepes
  • 50 – 61: elégséges
  • 0 – 49: elégtelen

Tematika

Előadások

Web

  • 1. hét (Albert István): követelmények, webarchitektúra: statikus és dinamikus kiszolgálás; HTTP-kérés, -válasz, -kapcsolat, -státuszkódok; URI, URL: header, cache; API: REST, Postman
    • A 22. dián a telefonszámot tartalmazó URI az RFC 3986 alapján nem tartalmazhatna szóközöket.
  • 2. hét (Gincsai Gábor): az előző hét folytatása: HTML: elemek, attribútumok, oldalváz, block / inline, <head>, <p>, <a>, <img>, <ul>, <ol>, <li>, <table>, <form>, <input>, <label>, <select>, <datalist>, <audio>, <video>; validáció: pattern, required; állapotmegőrzés: session, cookie, GDPR; HTTPS: SSL, TLS (handshake), (self-signed) certificate, érvényesség, kulcs
    • Megjegyzés a 61. diához: habár a diasoron én nem láttam magyarázatot a name attribútum használatára, a vizsgán kérdezik. De legalább az egyik laboron szó esik róla.
    • Megjegyzés a 69. diához: a .webm-et valójában már mindegyik böngésző támogatja.[1]
  • 3. hét (Gincsai Gábor): CSS: ...; Bootstrap: grid, col, img-fluid, form; flexbox
    • Megjegyzés a 97. diához: a display: flow-root-ot valójában már mindegyik böngésző támogatja.[2]
    • Habár a diasoron én nem láttam magyarázatot a @media only screen query és a min-width használatára, a vizsgán kérdezik. De legalább az egyik laboron szó esik róla.
  • 4. hét (Gincsai Gábor): JavaScript: transpiler, összehasonlítás (Java), nyelvi elemek, változók, (logikai) típusok (konverzió), értékadás (strict), konstans, alapértelmezett érték, feltételes futtatás, objektumok, JSON (parse, stringify), tömbök, függvények, window, global scope pollution, scopes (shadowing); DOM: querySelector[All](), createElement(), textContent(), appendChild(), setAttribute(), firstChild(), nextSibling(); eseménykezelés: addEventListener(), bubble, stopPropagation(); session / local storage: setItem(), getItem(), removeItem(), clear(); closure, self-invoking / arrow (lambda) function, modul; new, this; prototípus, konstruktor, factory method, class, string interpolation, öröklés; folytatás a laboron: Promise: ...
    • Megjegyzés a 44. diához: habár a diasoron én nem láttam magyarázatot a confirm() függvény használatára, a vizsgán kérdezik. De legalább az egyik laboron szó esik róla – érdekességként.
    • Megjegyzések a 103. diához:
      • Arrow functionöket const-tal érdemes definiálni, mivel általában nem változik a tartalmuk.
      • Az Objektum nem adható vissza simán pontban szándékosan hibás változódeklarációk szerepelnek.
  • 5. hét (Albert István): TypeScript: transpiler, static typing (any, noImplicitAny), structural typing, deklaráció (var, let, const), null (strictNullChecks), undefined, type narrowing / assertion, non-null assertion, optional chaining, null coalescing, enum (sorszámozás), string / number literal (union), type annotation / alias, optional values, interface; class: static, constructor, readonly, protected, extends, super, private, erősen védett mező; function overload signatures, generic types, típuskényszer, metszettípus, spread, dekorátorok; modulok: export, import, típusdeklarációs fájl (.d.ts)
    • Az 52. dián az utolsó szöveges bekezdés pontosabban: míg a JavaScript tetszőleges típuson, a TypeScript csak number-ön tud toString-et hívni.
  • 6. hét (Albert István): Angular: MV*, architektúra, metaadatok, dekorátorok, komponensek, szolgáltatások, Component, string interpolation, adatkötés (@Input / @Output, CSS class / -stílus), események kötése, kétirányú adatkötés, attribútum / property, (strukturális / attribútum)direktívák (HostListener), ngIf, ngFor, direktíva, alkalmazás- / komponens-életciklus, lifecycle hooks, ngOnInit, ngOnChanges, SimpleChange, ngDoCheck
    • Megjegyzés a 26. diához: az [src]-t pont nem érdemes használni, mivel az ngSrc jobban optimalizált.
  • 7. hét (Albert István): az előző hét folytatása: ngModule, bootstrapping, (im)pure (Reverse)Pipe; szolgáltatások (DI, scope, interface): HttpClient; szinkronitás, számosság (Observable), routing (RouterOutlet, RouterLink), linkek, Guard, (reaktív) formok (ellenőrzés), szinkron adatfolyam, vezérlők, komponensstílusok, témák, animáció

Android

  • 8. hét: szünet
  • 9. hét (Gazdi László): alapok, Java; View (XML): TextView; eseménykezelés, Kotlin; Activity, Service, content provider, BroadcastReceiver; manifest, erőforrások; .dex compiler (Dalvik bytecode), .apk; activity lifecycle (callback függvények, állapot mentése, váltás)
  • 10. hét (Gazdi László): Activity: back stack, vezérlés; Intent: típusai, részei, explicit / implicit, extras, képességek, filter; startActivityForResult(), onActivityResult(); erőforrások (i18n); UI: viewBinding; dpi, dp, sp; LinearLayout, RelativeLayout, ConstraintLayout; padding és margin
  • 11. hét (Pásztor Dániel): View: getLayoutInflater(), validáció, Menu, ActionBar, Toolbar; PopupWindow, AlertDialog, Snackbar; style, Theme; grafikák, animációk
  • 12. hét (Gazdi László): Fragment: életciklus, csatolása (statikusan és dinamikusan), FragmentManager, FragmentTransaction, kommunikáció, DialogFragment; navigation: component, graph; RecyclerView: ViewHolder, Adapter; perzisztens adattárolás: (Shared)Preferences, SQLite, ORM, room, javasolt architektúra; fájlkezelés: internal / external storage, statikus fájlok, nyilvános lemezterület; BaaS: Firebase; content provider: elérése (CONTENT_URI), műveletek, engedélyek, Cursor, ContentResolver, CRUD
    • Megjegyzés az 51. diához: a BLOB is egy támogatott adattípus.
  • 13. hét (Gazdi László): Jetpack Compose: @Composable (5 szabálya), @Preview, layoutok (Column, Row, Box), weight, Alignment és Arrangement, Modifier, Scaffold, TextField, Material Design; mappastruktúra, composition / initial composition / recomposition, adatok átadása; ViewModel: MVVM, MVI; navigation graph: funkciók, paraméterek, konstansok; dialógusok: AlertDialog; listák: lazy loading; szálak és coroutine-ok: suspending functions; flow
  • 14. hét (Gazdi László): hálózati kommunikáció: near-field: NFC, Bluetooth (LE), Nearby; web: TCP/IP socket (InputStream, OutputStream), UDP (Kyronet); HTTP(S): kapcsolatok kezelése, könyvtárak, timeout; aszinkron kommunikáció; adatformátumok: JSON, XML; REST: Retrofit (entitások, API); BroadcastReceiver: események, intentek (BOOT_COMPLETED); Service: készítése, (működési) típusok, limitációk, megvalósítás, életciklusmodell, kezelés, műveletek végrehajtása; runtime permissions: típusai, kezelése (kérés), best practice, Jetpack Compose
    • Megjegyzés a 14. diához: a Nearby Messagest 2023, a Nearby Notifications-t pedig már 2018 decemberében megszüntették.
  • 15. hét: szünet

Laborok

https://bmeviaubb03.github.io/laborok/

Házi feladatok

Web

A házi feladat során egy Angular alapú webalkalmazást kell készíteni.

Android

Az előadásokon és laborokon bemutatott technológiák segítségével egy komplex alkalmazás készítése önálló funkcionalitással.

Vizsga

Kvíz

Web

2023. tavasz

  • Mintavizsga
    • Mi az a TypeScript-dekorátor? Milyen szintaktikával használjuk? (kifejtős)
      • kb. ugyanaz, mint Pythonban
      • módosítani lehet vele egy osztályt vagy annak tagjainak működését
      • pl.:
        function logged(originalMethod: any, context: ClassMethodDecoratorContext) {
            return (...args: any[]) => {
                try {
                    console.log("Calculation started...");
                    return originalMethod.call(this, ...args);
                }
                finally {
                    console.log("...finished!");
                }
            }
        }
        
        class Calculator {
            @logged
            add(a: number, b: number) {
                return a + b;
            }
        }
        
        const calculator = new Calculator();
        calculator.add(1, 9);
        

2024. tavasz

  • A vizsga kifejtős kérdései
    • Mik az overload szignatúrák? Hogyan kell őket használni?
      • egy függvénynek többféle számú és típusú bemeneti változóját lehet velük definiálni
      • pl. az alábbi kód első két sorában:
        function makeDate(epoch: number): Date;
        function makeDate(year: number, month: number, day: number): Date;
        function makeDate(epochOrYear: number, month?: number, day?: number): Date {
          if (month !== undefined && day !== undefined) {
            return new Date(epochOrYear, month, day);
          } else {
            return new Date(epochOrYear);
          }
        }
        const dateFromEpoch = makeDate(1719082884);
        const dateFromDate = makeDate(2024, 6, 22);
        
        a 3. sorban található az implementációs szignatúra
        • mindig csak egy lehet belőle
        • nem lehet közvetlenül meghívni
    • Mire való a getElementById függvény? Hogyan lehet elérni?
      • egy adott ID-jű elem DOM-ban való megtalálására
        • így könnyen lehet a JS-kódból módosítani a DOM-ot
      • a globális document objektumnak van ilyen tagváltozója, azt kell meghívni a JS-kódban
      • pl.:
        <button id="disablerButton">
            Disable the other button
        </button>
        
        <button id="buttonToDisable">
            This button will be disabled
        </button>
        
        function disableButton(buttonId) {
            const button = document.getElementById(buttonId);
            button.disabled = true;
        }
        
        disablerButton.addEventListener("click", disableButton("buttonToDisable"));
        
    • Mi a különbség a block és inline típusú HTML-elemek között?
      • block
        • pl.: <div>, <p>
        • a szülőjének teljes szélességét kitölti
        • új sorban jelenik meg
      • inline
        • pl.: <a>, <span>
        • nem tölti ki a szülőjének teljes szélességét
        • ugyanabban a sorban jelenik meg
          • így lehet formázni linkeket, vagy pl. highlightolni (kihúzni) szöveget
          • csak a tagen belüli szövegre vonatkozik
    • Mire valóak az űrlapok?
    • Mire való egy űrlap elemeiben a name attribútum?
      • egyes beviteli mezők elnevezésére
        • az űrlap beküldésekor a kliens ezeket használja a szervernek küldött adatok megnevezésére
          • GET esetén: https://foo.com/?name1=value1&name2=value2
          • POST esetén: a fenti, ? utáni rész kerül a bodyba
      • a JS-kódban a document.getElementByName() használatakor erre lehet hivatkozni
        • ezzel könnyen manipulálható a DOM
    • Mire való egy .d.ts kiterjesztésű fájl?
      • declaration file
      • kizárólag a hozzá tartozó JavaScript-fájl típusinformációit tartalmazza
      • gyakorlatilag ugyanaz, mint Pythonban a type stub, de a TypeScript fordításidőben jelzi a típusokkal kapcsolatos problémákat (Pythonban ezeket csak az IDE mutatja)
    • Milyen előnyei vannak a dependency injection használatának?
      • separation of concerns
        • az injektor a felelős a dependency létrehozásáért, életciklusáért
          • teljesen független a dependency életciklusa a komponensétől
            • újrafelhasználható
          • erősebb dekompozíció
            • jobb tesztelhetőség
          • a komponens kódja így rövidebb lesz
        • csak az injektornak kell ismernie a függőségi gráfot
    • Mire szolgál az Angular ngIf direktívája?
      • elemek feltételes megjelenítésére
      • pl.:
        <div *ngIf="train">
            <p>
                This is the {{train.departureTime}} {{train.type}} service to {{train.destination}}.
            </p>
        </div>
        
      • az *ngIf attribútumban található kifejezést értékeli ki
        • itt a komponens .ts fájljában található változókra (is) hivatkozhatunk, melyekre adatkötést hoz létre
        • ha az értéke true, megjeleníti az elemet
        • ha false, törli a teljes elemet
      • lehet else ága is
        • ha sok if-else ág van, érdemes az ngSwitch-et használni helyette

Android

2024. tavasz

  • A diasorokon szereplő kifejtős kérdések
    • 9. hét
      • Milyen lehetőségeink vannak a fejlesztés közbeni debugolásra?
      • Miket kell tartalmaznia a manifestnek?
      • Mit értünk erőforrás-minősítő alatt?
      • Magyarázza el a fordítás mechanizmusát!
      • Mit jelent az obfuszkálás?
      • Az Activity callback életciklus-függvények felüldefiniálásakor meg kell-e hívni kötelezően az ősosztály implementációját? Miért?
      • Ha A Activity-ről átváltunk a B Activity-re, milyen sorrendben hívódnak meg az életciklus( callback )függvények?
        • ...
    • 10. hét
      • Magyarázza el az Activity back stack működési elvét!
      • Hogyan kell egy Activity-t indítani, ha vissza akarunk kapni adatot tőle?
      • Hogyan működik az implicit Intent?
      • Mit értünk sűrűségfüggetlen pixel alatt?
      • Egy 320 dpi-s képernyőn 1.dp hány darab pixelnek felel meg?
      • Sorolja fel a legfontosabb androidos layoutokat!
      • Hogyan támogatja az Android a lokalizációt?
    • 11. hét
      • Mi a LayoutInflater feladata?
      • Hogyan lehet elkészíteni és kezelni egy menüt?
      • Hogyan adható meg, hogy egy stílus az egész alkalmazásra érvényes legyen?
    • 12. hét
      • Mire használhatók a Fragment-ek?
      • Hogyan csatolhatók a Fragment-ek?
      • Hogyan kommunikálhatnak a Fragment-ek egymással?
      • Mire jó a RecyclerView? Mik az előnyei?
      • Milyen adattárolási lehetőségeket ismer?
      • Mire használható a SharedPreferences?
      • Hogyan támogatja az Android az adatok adatbázisban tárolását?
      • Sorolja fel az ORM alapelveit!
      • Milyen lehetőségek vannak a fájlrendszerben való adattárolásra?
      • Mire jó egy content provider?
      • Milyen formában adja vissza az adatokat egy content provider?
    • 13. hét
      • Mik a Jetpack Compose használatának előnyei?
      • Milyen Jetpack Compose layoutokat ismer? Jellemezze őket!
      • Mik a Jetpack Compose alapelvei?
      • Miért hatékony módszer a recomposition?
      • Vázolja fel, milyen Jetpack Compose-architektúrákat ismer!
      • Mire használható a lazy loading?
      • Mik azok a coroutine-ok?
      • Mire való a flow, és hogyan használjuk?
    • 14. hét
      • Milyen rövidtávú kommunikációs technológiákat ismer?
      • Milyen hosszútávú kommunikációs technológiákat ismer?
      • Mi a különbség az UDP és a TCP/IP között?
      • Hogyan kell végezni a hálózati kommunikációt?
      • Mire szolgál a Retrofit library?
      • Milyen módszereket ismer a BroadcastReceiver-ek regisztrálására?
      • Hogyan biztosítható, hogy egy bizonyos típusú broadcastot megkapjon a komponensünk?
      • Milyen típusú Service-eket ismer?
      • Mire kell nagyon figyelni egy Service írásakor?
      • Milyen engedélykategóriákat ismer?
      • Milyen fázisai vannak a veszélyes engedélyek kérésének?
  • Vizsga
    • Hogyan tudunk saját stílust definiálni? Hogyan tudjuk ezt a stílust az egész alkalmazásra érvényesíteni? (kifejtős)
      • View
        • Saját stílust a res/values/styles.xml fájlban egy <style> tag, majd ez alatt további <item> tagek hozzáadásával lehet definiálni.
        • A manifest fájl <application> tagjébe kell felvenni egy android:theme attribútumként, pl. így: <application android:theme="@style/CustomStyle">.
      • Jetpack Compose
        • Saját stílust egy @Composable függvény (pl. MyTheme) létrehozásával lehet definiálni, melyben pl. a MaterialTheme függvényt az általunk választott paraméterekkel hívjuk meg.
        • A MainActivity class setContent függvényében az App függvény hívását a MyTheme függvény hívásába kell ágyazni.
    • Mi a Fragment? (kifejtős)
      • objektumok, melyek...
        • a képernyő egy nagyobb részéért felelősek
          • résznézeteket írnak le
          • Activity-kbe lehet őket ágyazni
            • egyszerre többet is
          • növelni lehet velük a modularitást
        • és / vagy a háttérben munkát végeznek
    • Mire és hogyan használható egy flow? (kifejtős)
      • A flow egy Python generatorhoz vagy egy Java Streamhez hasonló változótípus.
        • Egy Python generatorhoz hasonlóan több visszatérési értéke is lehet.
        • Egy Java Streamhez hasonlóan lehet mapelni vagy filterezni.
      • Segítségével pl. fel lehet iratkozni egy adatfolyamra, hogy onnan folyamatosan kapjunk frissítéseket.
      • A Flow<> típusú változó .collect { } függvényét meghívva egy lambda kifejezést lehet végrehajtani a kapott értékkel.
    • Vázolja fel a képen látható nézet kódját Jetpack Compose segítségével! A kódnak nem kell tökéletesnek és teljesnek lennie, de a lényegi részek szerepeljenek benne. A képen egy képernyő, melynek közepén teljes szélességben egy Email feliratú szövegmező látható, alatta egy Password feliratúval. Mindkét szövegmezőbe ugyanazon látható szöveg van beírva. Alattuk pedig egy Login gomb látható, szintén a képernyő teljes szélességében.
      • @Composable
        fun loginPage(
            modifier: Modifier = Modifier,
        ) {
            var emailAddress = "klaf@aut.bme.hu"
        
            Column() {
                TextField(
                    placeholder = "Email",
                    value = emailAddress,
                )
                HorizontalDivider()
                TextField(
                    placeholder = "Password",
                    value = emailAddress,
                )
                HorizontalDivider()
                Spacer()
                Button() {
                    Text(text = "Login")
                }
            }
        }
        
      • Vázolja fel a képen látható nézet kódját a View framework segítségével! A kódnak nem kell tökéletesnek és teljesnek lennie, de a lényegi részek szerepeljenek benne.
        • <RelativeLayout
              android:background="#000000">
              
              <ImageView
                  android:src="@drawable/one_ring_image"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_centerVertical="true"
                  android:padding="16dp" />
              
              <LinearLayout
                  android:layout_toEndOf="@id/one_ring_image"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:orientation="vertical"
                  android:layout_centerVertical="true"
                  android:background="#FFFFFF">
                  
                  <TextView
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:text="J. R. R. Tolkien"
                      android:textColor="#000000"
                      android:textSize="24sp"
                      android:layout_marginBottom="8dp" />
                  
                  <TextView
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:text="The Lord of the Rings"
                      android:textColor="#000000"
                      android:textSize="24sp" />
                  
              </LinearLayout>
          
          </RelativeLayout>
          
1. félév
2. félév
3. félév
4. félév
5. félév
6. félév