Hey,
Ik zit aan een Android app te werken, en ben bezig met een schermpje dat een aantal verschillende zaken over het internet moet ophalen en uiteindelijk aan de gebruiker moet tonen. De app roept via een http post een webservice aan die wat json terug stuurt. Dit moet natuurlijk in een achtergrond thread gebeuren om de UI niet te laten vastlopen.
Nu weet ik dat Android een aantal handige classes heeft om dit te doen, met name de AsyncTask class. Ik weet hoe ik die gebruik, er zijn alleen een aantal 'problemen':
Ik zou deze class dan op deze manier kunnen gebruiken:
Dat is een stuk minder code en een stuk makkelijker schrijven dan weer een nieuwe AsyncTask te moeten implementeren (even aangenomen dat ik een dergelijke operatie op heel veel plekken vaker moet doen, wat uiteraard wel zo is).
Ik heb echter geen idee hoe ik dit moet doen. Ik zit teveel in .NET termen te denken, waar de ??? fields dingen als Actions en Funcs kunnen zijn. Voor zover ik weet bestaat dit niet in Java.
De oplossing die ik steeds tegen kom is om de Activity (waar ik deze code dus in draai) een interface te laten implementeren (zeg IDataLoader) die een methode 'getData' en 'getDataFinished' voorschrijft. De GetDataTask class kan dan (in plaats van twee methodes) een IDataLoader referentie accepteren in z'n constructor, en daarop die twee methodes aanroepen.
Dit werkt in principe wel, maar er is een probleem waardoor ik dit niet kan gebruiken. Dit interface zal namelijk generic moeten zijn, een input en een output type parameter (in dit geval Integer als input, User als output). Stel nou dat ik in dezelfde view ook nog een lijst met berichtjes (Message) moet ophalen, dan heb ik dus nog een GetDataTask instantie nodig, deze keer met Message als parameter. Dat betekent dat mijn Activity dus IDataLoader<Integer, User> en ook IDataLoader<Integer, ArrayList<Message>> moet implementeren. En dat kan blijkbaar niet, Java gaat zeuren dat ik niet twee keer hetzelfde interface met verschillende type parameters mag implementeren.
Dus dit gaat zo niet werken...
Is er een andere manier om dit te doen? Bedankt!
Ik zit aan een Android app te werken, en ben bezig met een schermpje dat een aantal verschillende zaken over het internet moet ophalen en uiteindelijk aan de gebruiker moet tonen. De app roept via een http post een webservice aan die wat json terug stuurt. Dit moet natuurlijk in een achtergrond thread gebeuren om de UI niet te laten vastlopen.
Nu weet ik dat Android een aantal handige classes heeft om dit te doen, met name de AsyncTask class. Ik weet hoe ik die gebruik, er zijn alleen een aantal 'problemen':
- Voor elke operatie moet ik een nieuwe class maken die AsyncTask extend
- Ik moet elke keer weer de Activity mee geven aan die class zodat ik toegang heb tot bijvoorbeeld UI views (labels etc) of een ProcessDialog kan sluiten
- Het is een hele sloot code die (volgens mij) niet nodig is
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| public class GetDataTask<E> extends AsyncTask<Integer, Void, E> { private ???<Integer, E> getDataMethod; private ???<E, Void> finishedMethod; public GetDataTask(??? method1, ??? method2) { getDataMethod = method1; finishedMethod = method2; } @Override public E doInBackground(Integer... args) { // Deze methode draait in een achtergrond thread // Hier wil ik de methode aanroepen die de data ophaalt, deze methode kan dus ELKE methode zijn // zolang hij maar een int als argument heeft en een 'E' terug geeft int id = args[0]; E result = getDataMethod.invoke(id); return result; } @Override public void onPostExecute(E value) { // Deze methode wordt aangeroepen zodra de achtergrond thread klaar is // hier wil ik dus de methode aanroepen die de UI kan updaten finishedMethod.invoke(value); } } |
Ik zou deze class dan op deze manier kunnen gebruiken:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| private ProcessDialog dialog; public void onSomeButtonClicked() { dialog = ProcessDialog.show("Retrieving user..."); // Get user details: int userId = 34; GetDataTask<User> task = new GetDataTask<User>(loadUser, loadUserFinished); task.execute(userId); } public User loadUser(int id) { // Laad User details over het internet, duurt een tijdje return Networking.getUserFromNetwork(id); } public void loadUserFinished(User user) { // Klaar met user details ophalen, update de UI txtUserName.setText(user.username); dialog.dismiss(); } |
Dat is een stuk minder code en een stuk makkelijker schrijven dan weer een nieuwe AsyncTask te moeten implementeren (even aangenomen dat ik een dergelijke operatie op heel veel plekken vaker moet doen, wat uiteraard wel zo is).
Ik heb echter geen idee hoe ik dit moet doen. Ik zit teveel in .NET termen te denken, waar de ??? fields dingen als Actions en Funcs kunnen zijn. Voor zover ik weet bestaat dit niet in Java.
De oplossing die ik steeds tegen kom is om de Activity (waar ik deze code dus in draai) een interface te laten implementeren (zeg IDataLoader) die een methode 'getData' en 'getDataFinished' voorschrijft. De GetDataTask class kan dan (in plaats van twee methodes) een IDataLoader referentie accepteren in z'n constructor, en daarop die twee methodes aanroepen.
Dit werkt in principe wel, maar er is een probleem waardoor ik dit niet kan gebruiken. Dit interface zal namelijk generic moeten zijn, een input en een output type parameter (in dit geval Integer als input, User als output). Stel nou dat ik in dezelfde view ook nog een lijst met berichtjes (Message) moet ophalen, dan heb ik dus nog een GetDataTask instantie nodig, deze keer met Message als parameter. Dat betekent dat mijn Activity dus IDataLoader<Integer, User> en ook IDataLoader<Integer, ArrayList<Message>> moet implementeren. En dat kan blijkbaar niet, Java gaat zeuren dat ik niet twee keer hetzelfde interface met verschillende type parameters mag implementeren.
Dus dit gaat zo niet werken...
Is er een andere manier om dit te doen? Bedankt!