2012-08-10 16 views
12

Nella mia app Android, ho scaricato un'immagine dal cloud. Il download viene eseguito in una discussione e nello stesso thread ho anche impostato una visualizzazione dell'immagine con l'immagine appena scaricata. Dopo aver impostato l'immagine, quindi chiamo postinvalidate().Come aggiornare immediatamente la vista immagine

Tuttavia, l'immagine non viene immediatamente visualizzata. C'è un modo per far sì che il redraw avvenga immediatamente? Ho bisogno di un modo per attivare un ciclo di disegno.

risposta

38

Ogni classe che deriva dalla classe View ha la invalidate() e il metodo postInvalidate(). Se viene chiamato invalidate(), comunica al sistema che la vista corrente è cambiata e dovrebbe essere ridisegnata il appena possibile. Poiché questo metodo può essere chiamato solo dal tuo UIThread un altro metodo è necessario quando sei non nel UIThread e vuoi comunque notificare al sistema che la tua Vista è stata cambiata. Il metodo postInvalidate() notifica il sistema da un non-UIThread e la vista viene ridisegnata nel successivo eventloop sul UIThread il prima possibile.

Nel tuo caso puoi ottenere ciò che desideri con l'aiuto di AsyncTask (un thread backround intelligente). AsyncTask abilita l'uso corretto e semplice del thread dell'interfaccia utente. Questa classe consente di eseguire operazioni in background (scarica l'immagine in background nel tuo caso) e pubblica risultati (imposta la tua bitmap sul tuo ImageView) sul thread dell'interfaccia utente senza dover manipolare thread e/o gestori.

Un'attività asincrona è definita da un calcolo eseguito su un thread in background e il cui risultato è pubblicato nel thread dell'interfaccia utente. Un'attività asincrona è definita da 3 tipi generici, denominati Params, Progresso e risultato e 4 passaggi, chiamati begin, doInBackground, processProgress e end.

i 4 passi

Quando viene eseguita un'attività asincrona, il compito passa attraverso 4 fasi:

onPreExecute(), invocati nel thread UI immediatamente dopo l'operazione viene eseguita. Questo passaggio viene normalmente utilizzato per configurare l'attività, ad esempio visualizzando una barra di avanzamento nell'interfaccia utente prima di scaricare l'immagine dal cloud e utilizzata per fornire una buona esperienza utente.

doInBackground(Params...), richiamato sul thread in background immediatamente dopo l'esecuzione di onPreExecute(). Questo passaggio viene utilizzato per eseguire calcoli di background che possono richiedere molto tempo. I parametri dell'attività asincrona vengono passati a questo passo. Il risultato del calcolo deve essere restituito da questo passaggio e verrà passato all'ultima fase. Questo passaggio può anche utilizzare publishProgress (Progress ...) per pubblicare una o più unità di avanzamento. Questi valori sono pubblicati sul thread dell'interfaccia utente, nel passaggio onProgressUpdate (Avanzamento ...).

onProgressUpdate(Progress...), richiamato sul thread dell'interfaccia utente dopo una chiamata a publishProgress(Progress...). I tempi dell'esecuzione non sono definiti. Questo metodo viene utilizzato per visualizzare qualsiasi forma di avanzamento nell'interfaccia utente mentre il calcolo dello sfondo è ancora in esecuzione.

onPostExecute(Result), richiamato sul thread dell'interfaccia utente al termine del calcolo dello sfondo. Il risultato del calcolo dello sfondo viene passato a questo passaggio come parametro in tale metodo è possibile impostare la bitmap su imageView e invalidare le visualizzazioni

+4

Mucca santa, ecco un +1 – Korcholis

2

Hai provato a utilizzare invalidate()? Costringe la vista ridisegno immediatamente e non durante il successivo ciclo

+0

Ma questo non è il thread UI però ... – user1583075

+0

Non ho provato in questo momento, ma sembra puoi farlo quando in 'onPostExecute()'. Vedi un riferimento [qui] (http://stackoverflow.com/questions/3960886/problem-with-calling-invalidate-in-async-task-thread-in-android) – Korcholis

+0

Oh, vedo il tuo problema ora. Mi aspettavo tutto il tempo che stavi usando 'AsyncTask'. Colpa mia, scusa – Korcholis

0
new Thread(new Runnable() { 

      @Override 
      public void run() { 
       // TODO Auto-generated method stub 
       while (!socket.isClosed()) { 
        imgArray = receiveImagebytes(); 
       } 
      } 
     }).start(); 

     try { 
     Thread.sleep(5000); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 


while (!socket.isClosed()) { 
      runOnUiThread(new Runnable() { 

       @Override 
       public void run() { 
        // TODO Auto-generated method stub 

        imageView.setImageBitmap(BitmapFactory.decodeByteArray(imgArray, 0, imgArray.length)); 
        imageView.invalidate(); 
       } 
      }); 
2

L'invalido non funziona. Cambiando l'uri o l'url o il percorso dell'immagine temporaneamente e tornando al percorso richiesto funziona. Ad esempio, se ho

image_url="myhost/img.png"; 
himg.setImageUrl(image_url, imageLoader); 

posso aggiornare questo come:

himg.setImageUrl(null, imageLoader); 
himg.setImageUrl(image_url, imageLoader) 
Problemi correlati