Java-Swing UI单独的套接字逻辑

时间:2018-06-27 07:56:23

标签: java multithreading swing sockets user-interface

我变得绝望,我基于客户端-服务器原理开发了一个简单的Java多用户聊天程序。我已经编写了一个基本的多线程服务器应用程序,并且运行良好。我的问题是基于Swing GUI工具包的客户端。具有运行时循环的基本UI,用于在后台接收消息。我的问题是我想将套接字逻辑与UI分开,这意味着在最好的情况下,我有两个不同的类,一个用于套接字运行时循环,另一个用于管理UI。由于该问题,运行时循环必须将消息通知/添加到UI,所以它们彼此依赖。

  • MessengerView是我的主要课程,其中包含swing ui和所有依赖的组件。目前,该类还包含套接字逻辑,但是我想将它们提取到外部类中。
  • ClientRuntime应该包含套接字逻辑的类...

我的问题是,如何分离它们以及如何连接它们?例如,我尝试通过注册这样的方法来尝试类似摆动的事件:

addListener(MessageArrivedListener listener);
emitMessageArrivedEvent(String message);

问题是,如果事件数量增加,这将非常令人困惑!如前所述,我的第二个选择是将套接字逻辑和ui设计保留在一个类中,但是我认为这是一个坏主意,因为这使得很难为其编写单元测试或发现错误...

在使用C ++的时候,有时会使用朋友类来解决此问题,因为这样可以访问其他类的类成员!但是这种解决方案通常也很混乱,我发现Java没有这样的选择。

那么还有其他方法可以保持swing小部件和套接字逻辑之间的连接,而无需将它们存储在同一类(文件)中吗?

2 个答案:

答案 0 :(得分:1)

how could I separate them and how could I connect them?

使用BlockingQueue连接它们-这是选择连接线程的方式的首选。

ClientRuntime类必须启动2个线程:一个从阻塞队列中获取请求并将其发送到服务器,第二个不断通过套接字从服务器读取消息并将其发送到UI线程。 UI线程已经为消息输入了阻塞队列:SwingUtilities.invokeLater(Runnable);对其进行了访问。 ClientRuntime类不能直接访问UI队列:它从MessengerView调用一个方法,并将其从套接字接收的内容,二进制数组或json字符串传递给该UI方法,并将其转换为某些{{ 1}}实际上会更新用户界面。

答案 1 :(得分:0)

  

他们互相依赖

嗯,他们不是真的。 “套接字”层仅关心启动,运行,发布一些消息以及停止。

实际上并不关心/完成所有事情,它只是在被告知时“启动”,处理输入/输出消息,在被要求时发布通知和“停止”。

这基本上是观察者模式,或者,如果您愿意,则是生产者/消费者模式。

因此套接字层需要定义一个愿意使用的行为或契约的“协议”。该合同的一部分将是“如何”通过观察者或通过阻止/只读队列生成有关新消息的通知的方法,这由您决定。

对于UI来说,它稍微复杂一点,因为Swing是单线程的,因此您不应长时间运行或阻塞操作来阻塞UI。在这里类似SwingWorker的地方会派上用场。

它基本上充当UI和套接字层提供的用于接收消息的机制之间的代理。消息从套接字层进入SwingWorkerSwingWorker然后publish将消息发送到UI的事件线程,然后可以安全地更新到UI

也许以Concurrency in SwingWorker Threads and SwingWorker开头

  

我的问题是,如何分离它们以及如何连接它们?例如,我尝试通过注册这样的方法来尝试类似摆动的事件:   问题是,如果事件数量增加,将非常令人困惑!

我不这样认为(恕我直言)。您想要做的是专注于事件的“类”。例如,从上面的内容中,您有“生命周期”事件和“消息”事件。我首先将它们分为两个单独的界面,因为对“消息”事件感兴趣的人可能对“生命周期”事件不那么感兴趣,这样您就可以划分观察者。

您想要尝试的重要概念是正确使用`接口来定义“合同”,这成为实现的“公开”视图,允许您根据自己的想法设计用于不同目的的不同实现变化和成长。这样可以使代码解耦,并允许您更改一部分而不会对API的其他部分产生不利影响