如何在java(Android)中实现c#事件行为

时间:2012-11-07 02:59:48

标签: c# java android

当我在c#中编程时,我经常使用事件。现在我想在Java中实现类似的东西。我知道这两种语言都不同,在实施这种机制方面存在一些差异。那么为了给出更好的图片,也许我会描述一下我想要的东西,因为我可能会混淆一些术语:

MyClass 包含处理启动 MyEvent 的代码以及在某些情况下启动该事件的一些代码。

MyEventArgs 是从 MyClass 传输数据的类,随着事件启动一起发送,因此处理 MyEvent 的函数有一些关于 MyClass 实例的状态。

还有 MyApp 类在main方法中包含 MyClass 的实例和代码处理 MyEvent 以及在内引发事件时MyClass 某些操作是在侦听 MyEvent 的代码中执行的。

如果仍然不清楚,我的意思是完全像c#机制背后的按钮点击,而不是按钮有我的类,有我的事件参数而不是鼠标事件args和我设计的行为而不是点击。

我试图谷歌解决我的问题的一些答案,例如我找到了以下网站:

http://javarevisited.blogspot.com/2011/12/observer-design-pattern-java-example.html http://www.javaworld.com/javaworld/javaqa/2002-03/01-qa-0315-happyevent.html

要么我刚丢失,我正在寻找不好的地方/使用错误的关键词,或者更多可能我无法理解这些例子中的任何内容/我无法将它们转换为我需要的方式。< / p>

我要求的是一些例子,或至少使用 MyClass, MyEvent, MyEventArgs 来处理此类机制的代码草案>名称,指向代码我应该在我的类中使用来引发事件和一些示例使用类和处理Main方法中的事件,所以它会帮助我解决这个问题。

==========编辑======

也许有一些像Android开发者这样的东西?我的目标是在我消除java之后开始进入移动应用程序开发。

==========编辑======

如果有人仍然感兴趣,这里有一些示例代码,它不使用我提到的名称,只是显示我正在寻找的内容:

并且没有确切的解决方案,也许somone会建议类似于我正在寻找的东西?

frmTest.cs

namespace SampleApp
{
    public partial class frmTest : Form
    {
        CountdownTimer ctmrTest;

        public frmTest()
        {
            InitializeComponent();
            ctmrTest = new CountdownTimer(100);
            ctmrTest.CountdownTimerTick += new CountdownTimer.CountdownTimerTickEventHandler(ctmrTest_CountdownTimerTick); 
        }

        void ctmrTest_CountdownTimerTick(object sender, CountdownTimerEventArgs ea)
        {
            lblTimer.Text = ea.timeString;
            if (ea.countdownFinished) countdownEnd();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            ctmrTest.Reset();
            ctmrTest.Start();
        }

        void countdownEnd()
        {
            MessageBox.Show("Finish");
        }
    }
}

CountdownTimer.cs

namespace SampleApp
{
    public class CountdownTimer
    {
        Timer tmrTicks = new Timer();
        int secondsLeft = 0;
        int numberOfSecondsToCountdown = 0;

        public bool IsWorking
        {
            get { return tmrTicks.Enabled; }
        }

        public CountdownTimer(int seconds)
        {
            ...
        }

        void tmrTicks_Tick(object sender, EventArgs e)
        {
            ...
            WhenCountdownTimerTick(new CountdownTimerEventArgs(secondsLeft, numberOfSecondsToCountdown, true));
        }

        public void Reset()
        {
            ...
            WhenCountdownTimerTick(new CountdownTimerEventArgs(secondsLeft, numberOfSecondsToCountdown, false));
        }

        public void Stop()
        {
            tmrTicks.Enabled = false;
        }

        public void Start()
        {
            ,,,
        }

        public delegate void CountdownTimerTickEventHandler(object sender, CountdownTimerEventArgs ea);

        public event CountdownTimerTickEventHandler CountdownTimerTick;

        protected virtual void WhenCountdownTimerTick(CountdownTimerEventArgs ea)
        {
            if (CountdownTimerTick != null)
            {
                CountdownTimerTick(this, ea);
            }
        }
    }
}

CountdownTimerEventArgs.cs

namespace SampleApp
{
    public class CountdownTimerEventArgs : EventArgs
    {
        public string timeString = "";
        public bool countdownFinished = false;

        public CountdownTimerEventArgs(int secondsLeft, int SecondsToCountdown, bool isfinished)
        {
            countdownFinished = isfinished;
            timeString = string.Format("{0:00}:{1:00}", secondsLeft / 60, secondsLeft % 60);
        }
    }
}

2 个答案:

答案 0 :(得分:3)

如果我理解正确(我刚刚开始学习C#),在Java中使用它的常规方法是使用观察者模式(监听器模式):

使用要在事件发生时调用的方法创建侦听器接口。 如果您愿意,该方法可以将一些事件参数和发送者作为参数。 例如:

public interface MyListener { // This is probably your MyEvent
    void myEventFired(Object sender, MyEventArgs eventArgs);
}

public class MyEventArgs {
    ...something...
}

要响应您的事件类的类需要实现上述接口。 (请参阅下面的示例(MyListeningClass))

好的,那么你需要一个类(或更多类)来激活你的事件: MyClass 。 通常 MyClass 对其他想要回复 MyClass '事件的类进行注册 他们自己用 MyClass 。 (或者更确切地说,使用 MyClass 的特定对象注册自己)。这允许 MyClass 对象知道事件发生时应告知哪些其他对象。

这通常是通过在触发事件的类中创建一个名为“add [ListenerName]”的方法来完成的 - 在本例中 MyClass 中的“ addMyListener ”。 为了使这个例子更简单,让我们假设只能是一个监听器,所以我们将其称为“ setMyListener ”:

public class MyClass {

    private MyListener listener = null;

    // This is a method which sometimes fires an event, by calling the fireEvent() method below
    public void doSomething() {
        ...
        if (something) {
            // Let's say the event happens if "something" is true. 
            // So now we "fire the event". What "firing the event" means, 
            // is just to call the "myEventFired" method in the listener.
            fireEvent();
        }
        ...

    }

    // this is called from the method above to fire the event - i.e. to tell the listener that the event has happened
    protected void fireEvent() {
        if (listener != null) {
            Object sender = this; 
            MyEventArgs eventArgs = new MyEventArgs(...something...);
            listener.myEventFired(sender, eventArgs);
        }
    }

    // This method is called by the listener, to register itself as listener on this object.
    // MyClass remembers the listener in the "listener" instance variable, so that 
    // when the event happens at some later point in time, it knows which object it  
    // has to tell it to.
    public void setMyListener(MyListener listener) {
        this.listener = listener;
    }
}

(要支持多个侦听器,只需要一个侦听器列表List<MyListener> listeners而不是MyListener listener实例变量,并创建一个addListener和removeListener方法而不是setListener方法。 Android API通常只允许一个监听器,所以我想我会显示该版本)

所以现在我们只需要想要听取这个事件的班级。即实现 MyListener 接口的类。 (这个类因此是一个倾听者)。一个简单的例子:

public class MyListeningClass implements MyListener {

    public MyListeningClass() {
        MyClass myClass = ...get the MyClass object from somewhere...;
        myClass.setMyListener(this);
    }

    // this is called by MyClass when the event occurs
    public void myEventFired(Object sender, MyEventArgs eventArgs) {
        System.out.println("EVENT HAPPENED!");
        System.out.println("Sender is: "+sender);
        System.out.println("MyEventArgs are: "+eventArgs);
    }    
}

(当然,如果你不想,你实际上不需要创建界面。你当然可以在MyClass中对MyListeningClass进行硬编码,但是使用接口来解决MyClass的风格更好彼此之间的MyListeningClass。以后它也可以更加扩展,允许除MyListeningClass之外的其他类也可以监听事件。)

Java API中有很多这样的例子。例如,正如您所提到的,SWING大量使用了侦听器 - 例如按钮单击。当然还有Android API。

我会看到我以后能否找到一些这样的例子,但是已经很晚了,我很累,所以也许明天:D(并修复任何拼写错误:D)。希望它有所帮助。

回顾:

  • MyClass (生成事件的类)需要某种方式告诉其他类事件发生时事件发生的时间。 它通过在事件发生时调用这些类中的方法来实现。

  • MyClass 能够在这些其他类中调用方法,他们必须实现一些接口。

  • 想要在事件发生时被告知的课程需要一种方法来告诉 MyClass 他们想要 被告知这件事。这就是我们需要 MyClass.setMyListener 方法的原因。 (或者如果我们允许多个侦听器: MyClass.addMyListener 方法)

(所以没有什么神奇的。这只是简单的方法调用。)



<小时/>

(注意,一个监听器接口通常被命名为“[事件名称]监听器”。因此,如果我们说,根据命名约定,我应该将其称为“MyEventListener”而不是“MyListener”。该事件被称为“MyEvent”。但对于这篇文章,我认为它看起来太长而且不那么简单。更新:现在我想起来,你实际上通常会从名称中省略“事件”,所以“MyListener”是正确的。例如,如果你有一个名为“OnClickEvent”的事件,你可以调用“OnClickListener”接口。)

答案 1 :(得分:0)

您最好的选择可能是使用Google Web Toolkit (GWT)。您可以使用与Visual Studio / C#相同的方式为GWT Widgets定义事件处理程序。

Eclipse甚至还有一个内置的窗口构建器插件。