2012-11-06 2 views
10

Ho un'app di riconoscimento della grafia: l'utente disegna con il dito, l'app riconosce i caratteri. Il motore di riconoscimento viene eseguito in un thread di lavoro con la minima priorità possibile: Thread.MIN_PRIORITY. È un algoritmo puramente CPU/memoria, nessun I/O qualunque. Tuttavia, quando il thread sta funzionando attivamente, l'interfaccia utente diventa piuttosto instabile. I tratti delle dita subiscono un ritardo notevole da visualizzare. Inoltre noto che gli eventi tattili si perdono.Quando il thread di lavoro funziona, l'interfaccia utente diventa instabile

Non è esattamente quello che avrebbe dovuto evitare il threading? Perché il thread dell'interfaccia utente è affamato di CPU? Come convincere il sistema a trattare il thread di lavoro come, beh, un thread in background con priorità bassa?

Sembra che il sistema introduca (volontariamente o a causa della mancanza di CPU) un ritardo tra invalidate() e onDraw(). Posso in qualche modo abbassare quel ritardo?

Test su hardware relativamente vecchio - HTC Magic con Android 2.1.

risposta

4

Aveva lo stesso problema, così ho fatto il mio thread:

  1. Thread.yield() dopo l'elaborazione di un pezzo di lavoro.

  2. Aggiornamenti limitati inviati al thread dell'interfaccia utente con un intervallo minimo di 500 ms (che causa molto meno ridisegno).

  3. Ha consentito all'operatore di lavorare su segmenti di dati prioritari, concentrandosi sull'aggiornamento delle viste con cui l'utente sta attualmente interagendo.

Ora l'intera interfaccia utente è davvero pigra, ma priva di lag.

Ecco cosa il metodo di pianificazione del mio lavoratore assomiglia (lavoro effettivo è fatto con il metodo del processo):

//--low priority 
Thread.currentThread().setPriority(Thread.MIN_PRIORITY); 

//--as long as there's more work to do, and not cancelled-- 
while (mPriorityBuffer.hasNext() && !isCancelled()) { 

    //--get the work with highest priority-- 
    Work next = mPriorityBuffer.getNext(); 

    //--do work-- 
    Update u = mProcessor.process(next); 

    // collect updates for main thread 
    mUpdates.push(u); 

    long timeNow = Calendar.getInstance().getTimeInMillis(); 
    if(timeNow - timeLast > 500){ 
     //--its been quite a while now, update ui-- 
     postUpdatesToMainThread(); 
     timeLast = timeNow; 
    } 

    //--let UI thread work on updates-- 
    Thread.yield(); 
} 
+0

La resa periodica ha avuto l'effetto migliore. –

+0

Ciao D., potresti correggere il rientro in questo blocco di codice? Inoltre, potresti provare ad aggiungere un [tag lingua] (http://meta.stackexchange.com/a/75019/321006) per cercare di impedire all'evidenziatore della sintassi di pensare che yield sia una parola chiave? Penso che l'evidenziatore automatico presupponesse che si trattasse di codice C#. – jrh

2

provare ad aggiungere Thread.sleep(1) nel ciclo principale metodo di riconoscimento dei caratteri

@Override 
public void run() { 
    while (!recognited) { 

    //do some script 

    try { 
     Thread.sleep(1); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    } 
} 

questo sonno permette di macchina virtuale per riprendere altro thread un po 'presto e spesso

+0

si scrive riconosciuto, btw. un Thread.yage può aiutare anche se non ho mai notato che ha avuto alcun effetto reale. – njzk2

+1

La resa funziona meglio, a quanto pare. Ancora, +1. –

1

E' possibile che il thread GUI è floaded con toccare eventi, se è così allora la soluzione è di introdurre pochi ms attendere sul thread dell'interfaccia utente e aumentare il thread di lavoro. Maggiori informazioni su questo qui:

https://groups.google.com/forum/?fromgroups=#!topic/android-developers/Oe6k1_bm38o

anche, forse si stanno elaborando i dati troppo, come se nessun movimento realmente accaduta, o movimento non è abbastanza significativo.

+0

Consulenza pertinente nella discussione: sposta l'elaborazione del tocco in 'dispatchTouchEvent'. –