Autore Topic: Modificare la classe IntentService in modo da gestire la coda degli Intent  (Letto 698 volte)

Offline sgotenks

  • Utente junior
  • **
  • Post: 57
  • Respect: +1
    • Mostra profilo
  • Dispositivo Android:
    Geeksphone zero
  • Sistema operativo:
    Windows
Avrei davvero bisogno che qualcuno mi illuminasse. Ho letto la documentazione qua e la ma  non riesco a cavare un ragno dal buco. Sto usando La classe astratta IntentService per eseguire dei download in background. La classe crea automaticamente un thread con una coda x accodare delle task (e se ho capito questo è fatto dal looper) e un handler per accodare le task da un altro thread.......

Il mio problema è questo, ipotizziamo che io metta in coda i download 1,2,3,4,5.......il primo parte, una volta finito inizia il secondo e così via.  Quello che vorrei poter fare è:
1) Poter interrompere un download in corso, ovvero mentre ad esempio il primo è in corso io in qualche modo comunico di stopparlo, e si passa in autimatico al secondo
2) Eliminare dei download in coda, ad esempio mentro sto scaricando il primo mando un mex che dice togli il numero 3 dalla coda...così che dopo il secondo si passi subito al quarto (l'eliminazione del terzo va benissimo che sia fatta finito la prima task ma prima che inizi la seconda)

Al momento navigo nel buio e siccome la classe IntentService non permette di gestire la coda di task, mi han consigliato di copiarla in una nuova classe dato che è corsta  (circa 150 righe) e aggiungere 2 metodi x fare quel che mi serve. (altre vie io non le ho trovate)

Ora questa è la classe astratta in questione:
Codice (Java): [Seleziona]
package market.finestraprincipale;


import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;

/**
 * An abstract {@link Service} that serializes the handling of the Intents passed upon service
 * start and handles them on a handler thread.
 *
 * <p>To use this class extend it and implement {@link #onHandleIntent}. The {@link Service} will
 * automatically be stopped when the last enqueued {@link Intent} is handled.
 */

public abstract class MyIntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

    public MyIntentService(String name) {
        super();
        mName = name;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("sono in onCreate della mia classe fica");

        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        System.out.println("sono in onstart della mia classe fica e startID = "+startId);
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    /*
    public void togliDallaCoda() {
     MessageQueue coda = mServiceLooper.myQueue();
     mServiceHandler.
    }
        */

    /**
     * Invoked on the Handler thread with the {@link Intent} that is passed to {@link #onStart}.
     * Note that this will be invoked from a different thread than the one that handles the
     * {@link #onStart} call.
     */

    protected abstract void onHandleIntent(Intent intent);
}

Ho capito come funziona all'incirca il tutto ma non trovo documentazione o esempi su come interagire con la coda e aggiungere questi 2 metodi.....qualcuno mi sa aiutare?
Grazie a tutti

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3489
  • Respect: +507
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:Modificare la classe IntentService in modo da gestire la coda degli Intent
« Risposta #1 il: 06 Settembre 2011, 18:35:48 CEST »
0
Non posso scriverti il codice perchè sarebbe un po' troppo lungo però io farei in questo modo (in realtà ho fatto una cosa del genere ma senza service).

Sostanzialmente gli ingredienti sono:

-Una coda bloccante che sia thread safe (come ad esempio una ConcurrentLinkedQueue)
-Un thread A che legge gli elementi dalla coda
-Un thread B che si occupa di fare il download

L'algoritmo, descritto a mo' di ricetta della spesa è il seguente:
-Nella coda bloccante inserisci man mano che arrivano degli oggetti che ti descrivono il download che devi fare, ti serviranno nel thread B per fare il download.
-Il thread A legge un elemento dalla coda, fa partire il thread B e va in wait.
-Il thread B elabora il download secondo le informazioni contenute nell'oggetto che leggi dalla coda e quando termina fa una notify in modo da far ripartire il thread A e far eseguire quindi un altro download.
-Un ipotetico metodo stop fa in modo che il thread B attualmente in esecuzione fermi quello che sta facendo (interrompendo il download) e chiama una notify per fare che il thread A legga un elemento dalla coda e faccia partire il download successivo.

Scusa se la spiegazione è un po contorta ;)


Offline sgotenks

  • Utente junior
  • **
  • Post: 57
  • Respect: +1
    • Mostra profilo
  • Dispositivo Android:
    Geeksphone zero
  • Sistema operativo:
    Windows
Re:Modificare la classe IntentService in modo da gestire la coda degli Intent
« Risposta #2 il: 07 Settembre 2011, 11:16:30 CEST »
0
Grazie, allora la spiegazione è chiara, nel senso che l'idea a grandi linee ce l'avevo............però non volevo implementare il tutto da zero se no ci metto 3 ore, la classe intentservice fa già tutto se non le 2 operazioni sopra citate...........

Tu quindi consiglieresti di rifare tutto da zero? Ma all'interno di un servizio? QUindi oltre al Thread dell'interfaccia grafica, dovrei creare altri 2 worker Thread: A e B? (o A è il thread che esiste gia?)

Sarei più per continuare sull'idea di modificare intentService.
Alla fine per bloccare il lavoro in corso potrei fare così: nel matedoto handleIntent ho 2 while: uno x fare il download e uno x che unzippa i file che scarico, potrei mettere che in questi while controlla una variabile interruzione == false e se la trova true ritorna subito. So che il blocco può avvenire solo quando entra nei 2 while ma alla fine son quelli le parti lunghe, le altre linee di codice le esegue in un lampo. Considerando che la classe intentService la chiamo con startService(intent) devo solo capire come passargli un particolare intent che lui riconosca come condizione di blocco del download in corso.

Mentre per togliere elementi dalla coda, se ho ben capito IntentService usa delle messageQueue, devo capire che metodo usare x togliere un determinato elemento dalla coda, e anche qui che intent passargli per farglielo fare..............se qualcuno ha idee, codice o esempi, gliene sarei grato.