Na het maken van deze app wordt van je verwacht dat je:
Bekijk onderstaand filmpje en maak de app.
Met een spinner kan gebruiker een keuze maken uit een aantal dropdown items. De items van een spinner worden aangemaakt met een ArrayAdapter. Hiervoor heb je een string-array of een ArrayList met strings nodig waar de item strings in zitten. In onderstaand codefragment wordt een ArrayAdapter gemaakt met behulp van de volgende paramaters:
Spinner spinner = (Spinner) findViewById(R.id.spinner); ArrayAdapter<String> adapter = new ArrayAdapter<>( this, android.R.layout.simple_spinner_item, currencies); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter);
De bedoeling van een spinner is dat de gebruiker een item kan selecteren. Hiervoor moet je de methode setOnItemSelectedListener op het spinnerobject aanroepen:
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView> parent, View view, int position, long id) { //TODO zorg dat juiste currency wordt gekozen mbv position param } @Override public void onNothingSelected(AdapterView> parent) { } });
In de methode onItemSelected kun je de paramater position gebruiken om te bepalen op welk item is geklikt.
Een ListView is een ViewGroup met items waar je doorheen kan scrollen. De items worden net als bij een spinner gemaakt met een Adapter.
In onderstaand filmpje uit de cursus developing Android Apps van Udacity wordt uitgelegd waarom een adapter wordt gebruik en waarom dit efficiënter is dan bijvoorbeeld een LinearLayout in een ScrollView plaatsen, wat hetzelfde effect zou hebben.
Onderstaand codefragment toont hoe je met behulp van een ArrayList met Strings een adapter maakt en aan een ListView koppelt. De parameters zijn, afgezien van de gebruikte layout hetzelfde als bij de spinner.
ArrayList<String> listItems = new ArrayList<>(); //TODO vul list met items ArrayAdapter<String> listViewAdapter = new ArrayAdapter<String>( this, android.R.layout.simple_list_item_1, listItems); listView.setAdapter(listViewAdapter);
De currency converter maakt gebruik van de json api van fixer.io. Je kunt bijvoorbeeld een get-request naar de volgende url sturen om de beschikbare wisselkoersen afgezet tegen de Amerikaanse Dollar op te halen:
http://api.fixer.io/latest?base=USD
Het resultaat is een String met de structuur van een JSON object
{ "base":"USD", "date":"2016-04-22", "rates":{ "AUD":1.2936, "BGN":1.7365, "BRL":3.5708, "CAD":1.2734, "CHF":0.97585, ... ... } }
Een JSON object begint en eindigt met een accolade. Daartussen zie je zogenaamde key-value pairs. De key is een string waarmee de value kan worden opgehaald. De eerste twee ("base" en "date") in bovenstaand resultaat zijn gewone key-value pairs waarbij de values strings zijn. De derde ("rates") is ook een key-value pair, alleen is de value ervan op zijn beurt weer een JSON object met zijn eigen key-value pairs. Op deze manier kunnen JSON objecten in JSON objecten worden genest.
Het JSON object wordt binnengehaald als een string. Hiermee kun je eenvoudig een object van de JSONObject klasse maken met behulp van één van zijn constructors:
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(jsonString );
} catch (JSONException e) {
e.printStackTrace();
}
We kunnen nu verschillende values opvragen met behulp van hun keys.
String date = jsonObject.getString("date"); JSONObject rates = jsonObject.getJSONObject("rates"); Double usd = rates.getDouble("USD");
Standaard werkt een Android app met één thread: de "UI thread". Deze thread toont de user interface die wacht op (luistert naar) events die plaatsvinden als gebruiker iets doet. De user interface hoort altijd te reageren op een handeling. Je wilt dus niet dat de app bevriest tot een bepaalde taak is uitgevoerd. Tijdrovende taken zoals het ophalen en verwerken van data moeten in een aparte thread worden afgehandeld.
Een asynchrone taak (asynchronous task) is een taak die in een aparte thread op de achtergrond draait. Omdat Android apps dit soort taken vaak gebruiken heeft het Android framework hiervoor een speciale klasse: AsyncTask die het makkelijk maakt om dit soort taken uit te voeren. De klasse heeft een aantal methoden die je kunt gebruiken:
De methoden van AsyncTask kennen drie soorten parameters:
Om AsyncClass te gebruiken moet je er een binnenklasse van maken. Daarbij moet je aangeven uit wat voor type objecten de bovengenoemde parameters bestaan. Onderstaande code laat zien hoe een AsyncTask binnenklasse er uitziet, waarbij alleen de (verplichte) methode doInBackground en de methode onPostExecute zijn gebruikt.:
class DownloadTaak extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params ) { String url = params[0]; String result = ""; //TODO definieer IO taak return result; } @Override protected void onPostExecute(String result) { //TODO ververs UI } } //start de thread bijvoorbeeld in de onCreate methode @Override protected void onCreate(Bundle savedInstanceState) { ... ... String url = BASE_URL + "USD"; new DownloadTaak.execute(url); }
In Android sla je strings op in een strings.xml resource bestand in de map values. Dit wordt vooral gedaan om je app geschikt te maken voor meerdere talen. Je kunt namelijk meerdere strings.xml bestanden maken en bij het maken ervan aangeven voor welke taal het bestand bedoeld is met de qualifier locale. Je hoeft dan alleen de string waardes te veranderen. De taal van je app wordt dan aangepast aan de ingestelde taal van de gebruiker.