繁体   English   中英

如何在Java中实现C#事件行为(Android)

[英]How to achieve c# event behavior in 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

而且要么我只是迷路了,我正在寻找不好的地方/使用了错误的关键字,要么还有可能我无法从这些示例中理解任何内容/我无法将其转换为我需要的方式。

我要的是一个示例,或者至少是一些代码处理草案,例如使用MyClass, MyEvent, MyEventArgs,名称,指向代码的此类机制的处理方法,我应该在我的类中使用该机制来引发事件,以及一些示例使用类和事件处理在Main方法中,这样可以帮助我确定这个问题。

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

也许有些事情对于Android开发人员来说是可用的? 我的目标是在我除掉Java之后开始从事移动应用程序开发。

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

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

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

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

如果我理解正确(我只是开始学习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的 -object知道哪些其他对象应该告知当事件发生。

通常,通过在引发事件的类中创建一个名为“ 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方法)

(因此,这没有什么神奇的。这只是简单的方法调用。)




(请注意,侦听器接口通常被命名为“ [事件的名称] Listener”。因此,根据命名约定,如果我们称事件被称为“ MyEvent”。但是对于这篇文章,我认为它看起来太长且不太简单。更新: 现在考虑之后,您实际上通常在名称中省略了“ Event”,因此“ MyListener”是正确的。例如,如果您有一个如果您调用“ OnClickEvent”事件,则调用接口“ OnClickListener”。)

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM