Beginning Android Games 2 nd Edition(6)を読んでキーボードイベント処理クラスを作成

3778 ワード

package com.badlogic.androidgames.framework.impl;

import java.util.ArrayList;
import java.util.List;

import android.view.View;
import android.view.View.OnKeyListener;

import com.badlogic.androidgames.framework.Input.KeyEvent;
import com.badlogic.androidgames.framework.Pool;
import com.badlogic.androidgames.framework.Pool.PoolObjectFactory;

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;
    }

    public boolean isKeyPressed(int keyCode) {
        if (keyCode < 0 || keyCode > 127)
            return false;
        return pressedKeys[keyCode];
    }

    public List<KeyEvent> getKeyEvents() {
        synchronized (this) {
            int len = keyEvents.size();
            for (int i = 0; i < len; i++) {
                keyEventPool.free(keyEvents.get(i));
            }
            keyEvents.clear();
            keyEvents.addAll(keyEventsBuffer);
            keyEventsBuffer.clear();
            return keyEvents;
        }
    }
}

このクラスは、前の記事のオブジェクトプールクラスを使用して、KeyEventインスタンスをキャッシュします.
クラスの実行手順は図で説明できます.
第一歩:UIスレッドから新しいイベント(event)を得る.この時プールにはまだ何もありませんでした.そこで、KeyEventのインスタンス(KeyEvent 1)を作成し、keyEventsBufferリストに挿入します.
UI thread: onKey() ->
           keyEvents = { }, keyEventsBuffer = {KeyEvent1}, pool = { }
ステップ2:メインスレッドのgetKeyEventsメソッドを呼び出します.getKeyEventsメソッドはkeyEventsBuffer listからインスタンスKeyEvent 1を取得し、keyEvents listに挿入して呼び出します.
ステップ3:UIスレッドから別のイベントを取得し、プールにはまだ何もありません.したがって、新しいKeyEventインスタンスが作成され、keyEventsBufferリストに挿入されますUI thread:onKey()->keyEvents={KeyEvent 1}、keyEventsBuffer={KeyEvent 2}、pool{}
ステップ4:メインスレッドがgetKeyEventsメソッドを再び呼び出し、面白いことが起こりました!keyEvents listはKeyEvent 1のインスタンスを保持しており、介入のループはこのイベントをプールに入れます.
その後、keyEventsリストをクリーンアップし、keyEventインスタンスをkeyEventsBufferに挿入します.この場合、KeyEvent 2は私たちが繰り返し利用できるKeyイベントです.
Main thread: getKeyEvents() ->           keyEvents = {KeyEvent2}, keyEventsBuffer = { }, pool = {KeyEvent1}
ステップ5:もう一つのKeyイベントがUIスレッドに到達し、今回はプールでfreeでKey Eventを入手し、このオブジェクトを再利用し、ゴミ回収を回避しました.
UI thread: onKey() ->           keyEvents = {KeyEvent2}, keyEventsBuffer = {KeyEvent1}, pool = { }