1

Recently I've been doing Android development with the book Beginning Android Games. It contains the following code:

public class KeyboardHandler implements OnKeyListener {
    boolean[] pressedKeys = new boolean[128];
    Pool<KeyEvent> keyEventPool;
    List<KeyEvent> keyEventsBuffer = new ArrayList<KeyEvent>();
    List<KeyEvent> keyEvents = new ArrayList<KeyEvent>();
    public KeyboardHandler(View view) {
        PoolObjectFactory<KeyEvent> factory = new PoolObjectFactory<KeyEvent>() {
            public KeyEvent createObject() {
                return new KeyEvent();
            }
        };
        keyEventPool = new Pool<KeyEvent>(factory, 100);
        view.setOnKeyListener(this);
        view.setFocusableInTouchMode(true);
        view.requestFocus();
    }
    public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
        if (event.getAction() == android.view.KeyEvent.ACTION_MULTIPLE)
            return false;

        synchronized (this) {
            KeyEvent keyEvent = keyEventPool.newObject();
            keyEvent.keyCode = keyCode;
            keyEvent.keyChar = (char) event.getUnicodeChar();
            if (event.getAction() == android.view.KeyEvent.ACTION_DOWN) {
                keyEvent.type = KeyEvent.KEY_DOWN;
                if(keyCode > 0 && keyCode < 127)
                    pressedKeys[keyCode] = true;
            }
            if (event.getAction() == android.view.KeyEvent.ACTION_UP) {
                keyEvent.type = KeyEvent.KEY_UP;
                if(keyCode > 0 && keyCode < 127)
                    pressedKeys[keyCode] = false;
            }
            keyEventsBuffer.add(keyEvent);
        }
        return false;
    }

Once again I was a bit confused on why synchronized was necessary, and the book states: "Remember that the events are received on the UI thread and read on the main loop thread, so we have to make sure none of our members are accessed in parallel. " First of all, I thought the UI thread was the same as the main thread(or main loop thread, is there a difference?) Say the UI thread is executing this code, therefore also receiving the events(since this class implements OnClickListener). Say the main loop, the while(!userquit) loop, runs on a seperate thread. How are the events read by the main loop thread? Also, shouldn't the main loop run on the UI thread? Is my notion about Event Handling correct? When a keyEvent occurs, the thread executing KeyboardHandler has the code onKey() executed. How are events received on the UI thread, but read on the Main Loop thread? Shouldn't events be recieved and handled on the same thread?

2 Answers2

0

In Android, you cannot access User-Interface components outside of the main thread. It prevents all sort of errors with multi-threading. To access a UI component, either way, you can use the context.runOnUiThread method which allows you to run your commands on the UI thread, just as the name suggests.

Another way would be using the synchronized keyword, which, just as explained in this answer, allows two threads to read and write to each other. That way, the synchronized keyword allows non-UI threads to still interact with UI components.

Eldar B.
  • 1,097
  • 9
  • 22
0

You are correct the main thread and ui thread are synonymous and the same thread.

You can easily confirm this like this:

getActivity().runOnUiThread(() -> {
   Log.d(TAG, "runOnUiThread is run by main looper: "+Looper.getMainLooper().isCurrentThread());
});

Which will output:

runOnUiThread is run by main looper: true

So the statement of the documentation

events are received on the UI thread and read on the main loop thread

is wrong or at least misleading.

A better phrasing would be

events are received on the UI thread and executed by the main looper on it.

What they most likely wanted to communicate is, that the rest of your application is NOT (or should not) run on the UI thread, but is manipulating the same data. So synchronizing might be neccessary here when suddenly you are on a different thread (the UI Thread) manipulating the same data.

Torge
  • 2,174
  • 1
  • 23
  • 33