0

I have two classes: An activity class that controls several widgets and then a custom SurfaceView class that implements a Thread. (Fairly common). I have implemented a simple custom listener in the SurfaceView class that I can trigger whenever certain values change in the thread that I want to update in various widgets in the Activity class.

public class MyActivity extends Activity{

    CustomView myThreadView = (CustomView)findViewById(...);

    myThreadView.setListener(new OnStatChangeListener(){
        public void onChange(int change){
            //Change various widgets based on value fed in.
        }
    });

    // All of the other things (View setups, listeners, onCreate, etc.)
}

The Thread class:

public class CustomView extends SurfaceView implements Runnable(){
    //.. The usual thread and View stuff.

    public sListener;

    public interface OnStatChangeListener {
        public onChange(int change);
    }

    public void setListener(OnStatChangeListener oscl){
        sListener = oscl;
    }

    public void externalAccessMethod(){
        // Some thing changes a stat that is reflected in the Activity's widgets.
        sListener.onChange(value);
    }

    public void methodRunByThread(){
        // Something else changes that I want to update.
        sListener.onChange(value);
    }

    // Everything else (not relevant).
}

Whenever I call the onChange from a method that was called by the Activity's class, it works without issue. However, whenever the thread itself updates it's state (in my case a redraw method) and I call the onChange method, I get a CalledFromWrongThread exception. Can someone explain why one works but not the other, and what the best practice is for actually implementing a widget update from a separate thread? A separate handler thread in the Activity does not seem necessary, since I know exactly when I am updating the value anyway.

SeaNick
  • 501
  • 1
  • 4
  • 14

1 Answers1

0

Because you only can access views from the UI thread. There's a single UI thread per application. Now you access the views from another thread which is not correct and results inh exception.

You can do either this:

in your Activity's onChange wrap everything in runOnUiThread

or better:

use Handlers instead of your own listeners (needs some learning but pays)

Alexander Kulyakhtin
  • 47,782
  • 38
  • 107
  • 158
  • I guess I understand this, but then what is the point of making a custom listener then if it's required that it's in a method that could be run in the activity instead anyway? – SeaNick Sep 28 '12 at 19:47