Обычно ли интерфейсы Java используются для настройки обработчиков событий, и есть ли у этого подхода скрытые недостатки?

Привет всем, я все еще относительно новичок в Java и ищу проверку работоспособности.

Я изучал этот Java-порт Cocos2D и заметил, что класс CCLayer имеет встроенные перехватчики для собственных сенсорных событий Android. Это здорово, но мне бы очень хотелось, чтобы такие объекты, как CCSprite, напрямую реагировали на события касания без необходимости прослушивания этих событий в слое и перебора всех дочерних элементов, чтобы найти, какие из них пересекаются с координатами x/y события. . Поэтому я решил, что это будет прекрасная возможность проверить свое понимание того, как настроить некоторые обработчики событий и создать подкласс CCSprite, который действительно прослушивает прикосновения без необходимости проходить через CCLayer, чтобы узнать об этом. Кроме того, я хотел иметь возможность назначать разные поведения разным экземплярам CCSprite на специальной основе без дальнейшего явного подкласса, подобно тому, как кнопки Android не нужно создавать подклассы только для того, чтобы дать им обработчик событий касания.

Вот что у меня получилось при первом проходе:

// My touch interface for all touchable CCNode objects.

package com.scriptocalypse.cocos2d;

public interface ITouchable {

    boolean onCCTouchesBegan();
    boolean onCCTouchesEnded();
    boolean onCCTouchesMoved();

}

А теперь класс, который использует интерфейс ITouchable для своих обратных вызовов...

public class CCTouchSprite extends CCSprite implements CCTouchDelegateProtocol {

    protected ITouchable mTouchable;

    public void setTouchable(ITouchable pTouchable){
        mTouchable = pTouchable;
        boolean enable = mTouchable != null;
        this.setIsTouchEnabled(enable);
    }

    public void setIsTouchable(boolean pEnabled){
            // code to enable and disable touches snipped...
    }



    /////
    //  And now implementing the CCTouchDelegateProtocol...
    /////
    public boolean ccTouchesBegan(MotionEvent event) {

        Log.d("hi there", "touch me");
        if(mTouchable != null){
        mTouchable.onCCTouchesBegan();
        }
        return CCTouchDispatcher.kEventHandled;  // TODO Auto-generated method stub
    }

    public boolean ccTouchesMoved(MotionEvent event) {

        if(mTouchable != null){
            mTouchable.onCCTouchesMoved();
        }
        return CCTouchDispatcher.kEventIgnored;  // TODO Auto-generated method stub
    }

    public boolean ccTouchesEnded(MotionEvent event) {
        Log.d("hi there", "not touch me");
        if(mTouchable != null){
            mTouchable.onCCTouchesEnded();
        }
        return CCTouchDispatcher.kEventIgnored;  // TODO Auto-generated method stub
    }

}

И, наконец, создайте экземпляр класса и реализуйте интерфейс...

final CCTouchSprite sprite = new CCTouchSprite(tex);
sprite.setIsTouchEnabled(true);
sprite.setPosition(CGPoint.ccp(160,240));
sprite.setTouchable(new ITouchable(){
    @Override
    public boolean onCCTouchesBegan() {

        Log.d("SWEET SUCCESS", "I got a touch through my interface!");

        return true;
    }

    @Override
    public boolean onCCTouchesEnded() {
        Log.d("SWEET SUCCESS", "You stopped touching my interface!");
        sprite.runAction(CCRotateBy.action(1, 360));
        return false;
    }

    @Override
    public boolean onCCTouchesMoved(){
        Log.d("SWEET SUCCESS", "You moved the touch");
        return false;
    }
});

Так что все это работает. Подкласс успешно регистрируется в сенсорном диспетчере Cocos2D, который успешно вызывает эти функции ccTouches и передает им MotionEvents, которые, в свою очередь, вызывают мои интерфейсные функции, если интерфейс был создан.

Является ли это «правильным» способом сделать это (определяйте «это» по своему усмотрению, начиная от использования интерфейсов для создания обработчиков событий и заканчивая работой с Cocos2D и вообще написанием Java)? Есть ли в этом недостатки, о которых я не знаю? Это как-то хуже для производительности, чем повторение всех объектов CCNode, которые являются дочерними элементами CCLayer? Если да, то как это может быть?


person scriptocalypse    schedule 03.03.2011    source источник
comment
Как вы получили setIsTouchEnabled() для CCSprite?   -  person LuxuryMode    schedule 07.02.2012


Ответы (2)


Я думаю, у вас есть основы для правильной настройки слушателя. Хотя есть некоторые вещи, которые я бы изменил.

Во-первых, сеттер setIsTouchable. Это странно. Вам нужен объект-слушатель для передачи событий касания вправо? Так что же будет делать этот сеттер, когда вы передадите его true (как в вашем примере)? Вы вырезали код, но установка логического поля в значение true кажется здесь неправильным, поскольку это поместит объект спрайта в несогласованное внутреннее состояние. Я бы просто бросил этот сеттер. Геттер может просто оценить, назначен ли mTouchable или null.

Во-вторых, зачем ограничивать себя одним слушателем? Измените mTouchable на mTouchables, представляющий собой список ITouchables. Затем измените setTouchable на addTouchable и, возможно, добавьте методы removeTouchable и clearTouchables. Таким образом, вы можете добавить несколько слушателей для разных вариантов поведения, которые должны реагировать на одни и те же события. Так работает и большинство других систем событий. Затем вы просто меняете isTouchable, чтобы проверить, пуст ли список или нет.

person Stijn de Witt    schedule 15.10.2011

scriptoclypse ... Я действительно не совсем понимаю ваш вопрос, но вы не получили никакого ответа, и да, интерфейсы и события очень похожи. На этом уровне я могу только отвечать на C#.

person JAL    schedule 04.03.2011
comment
Спасибо за ответ, пусть даже на C#. У вас, ребята, в мире С# есть преимущество, я думаю, в том, что С# изначально поддерживает делегатов, в то время как в Java они кажутся доступными только благодаря ловкости рук. Создание делегата для этих слушателей в приведенном выше коде, вероятно, было бы логичным следующим шагом. Спасибо за ресурс! - person scriptocalypse; 04.03.2011