[英]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.