Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Threading UI updates in Android

I've just started with android development and updating the UI is really bugging me :/

This is what I've got working so far -


package projects.Move;

import android.os.Bundle;
import android.view.View;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Color;

public class Move extends Activity {

    private float y = 0;
    private long now = 0;  
    private float delay = 75;
    private Paint paint = new Paint();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new SimpleMotion(this));
        paint.setColor(Color.BLACK);
    }
    private class SimpleMotion extends View {

        public SimpleMotion(Context context) {
            super(context);
        }

        @Override protected void onDraw(Canvas canvas) {

            float x = canvas.getWidth() / 2;
            canvas.drawColor(Color.WHITE);
            canvas.drawCircle(x, y, 30, paint);  
            if(System.currentTimeMillis() - now > delay) y++;    
            invalidate();
        }
    }
}

It works fine but everybody says that doing your graphics in the main thread, so I'm trying (and failing) to pass it off to another thread. Trouble is, I have absolutely no idea how since really I've never used Threads.

The examples that Google gives on using Threads doesn't seem to be very clear and I couldn't really follow it for what I want to do. Could I ask somebody out here to give me the most basic example of how I could do what I'm doing here efficiently using Threads?

Thanks in advance :)

like image 615
Mark D Avatar asked Sep 19 '10 11:09

Mark D


People also ask

Can we update UI from thread in Android?

In this case, to update the UI from a background thread, you can create a handler attached to the UI thread, and then post an action as a Runnable : Handler handler = new Handler(Looper. getMainLooper()); handler. post(new Runnable() { @Override public void run() { // update the ui from here } });

What is UI thread in Android?

User Interface Thread or UI-Thread in Android is a Thread element responsible for updating the layout elements of the application implicitly or explicitly. This means, to update an element or change its attributes in the application layout ie the front-end of the application, one can make use of the UI-Thread.

Which thread can update the user interface?

If you need to update UI from HandlerThread , post a message on UI Thread Looper and UI Thread Handler can handle UI updates.

Which method is used to set the updates of UI?

Android Thread Updating the UI from a Background Thread The solution is to use the runOnUiThread() method, as it allows you to initiate code execution on the UI thread from a background Thread.


1 Answers

Well, I guess there is some confusion going on here. You HAVE TO do your GUI updates from the main thread (also called the GUI thread) - otherwise you well get something like "Exception, blabla has leaked a view".

I guess what have misunderstood is that expensive operations, such as networking, should be done in a different thread than the main thread. And if you would like to update the GUI from the network thread you would do as ArtWorkAD says (or his links says).

So for what you want to do, you could achieve with something like replacing your SimpleMotion class with the following:

private class SimpleMotion extends View {

        public SimpleMotion(Context context) {
            super(context);

            new Thread(new Runnable() {
                public void run() {
                    while(true){
                        try {
                            Thread.sleep(75);
                            y++;
                            postInvalidate();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
              }).start();
        }

        @Override protected void onDraw(Canvas canvas) {

            float x = canvas.getWidth() / 2;
            canvas.drawColor(Color.WHITE);
            canvas.drawCircle(x, y, 30, paint);  
//            if(System.currentTimeMillis() - now > delay) y++;    
//            invalidate();
        }
    }

With your old code of having invalidate() in onDraw() you would continously be redrawing the gui even while there are no change to it.

The important part of the new code is postInvalidate(). This makes it possible to tell the GUI thread - from another thread - to redraw the GUI.

like image 166
Cpt.Ohlund Avatar answered Sep 28 '22 19:09

Cpt.Ohlund