In my android app, I download an image from the cloud. The download is performed in a thread and in that same thread I also set an image view with the newly downloaded image
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();
}
});
Invalidate doesn't work. Changing the uri or url or the path of the image temporarily and changing back to the required path works. For example, if i have
image_url="myhost/img.png";
himg.setImageURI(image_url, imageLoader);
I can refresh this as:
himg.setImageURI(null, imageLoader);
himg.setImageURI(image_url, imageLoader)
Each class which is derived from the View class has the invalidate()
and the postInvalidate()
method. If invalidate()
gets called it tells the system that the current view has changed and it should be redrawn as soon as possible. As this method can only be called from your UIThread another method is needed for when you are not in the UIThread and still want to notify the system that your View has been changed. The postInvalidate()
method notifies the system from a non-UIThread and the View gets redrawn in the next eventloop on the UIThread as soon as possible.
In your case you can achieve what you want with the help of AsyncTask
(an intelligent backround thread).AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations (download image in background in your case) and publish results (set your bitmap to your ImageView) on the UI thread without having to manipulate threads and/or handlers.
An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called begin, doInBackground, processProgress and end.
The 4 steps
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute()
, invoked on the UI thread immediately after the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface before downloading the image from cloud and that's used to provide a good user experience .
doInBackground(Params...)
, invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress...)
, invoked on the UI thread after a call to publishProgress(Progress...)
. The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing.
onPostExecute(Result)
, invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter in that method you can set the bitmap to your imageView and invalidate your views
Did you try using invalidate()? It forces the view to be redrawn immediately and not during the next cycle