最起码消息要包含发言人的信息吧,现在这样子连我说的还是对方说的话都区分不出来。String是不能胜任了,新加HiMessage类。 HiMessage放在客户端还是服务端呢?这取决于HiMessage是否要用于异步调用的返回类型。客户端的代码都要编译成Javascript,虽 说我不懂这玩意,但是我感觉它效率肯定快不了,高举云计算的口号,客户端尽量不留逻辑,得,updateMessages还就返回字符串数组吧,告诉我怎 么显示就行。将来哪怕要更具说话人改颜色,大不了改成用HTML,那也还是字符串。
添加HiMessage类
private int clientId;
private String content;
public HiMessage(int clientId, String content) {
this.setClientId(clientId);
this.setContent(content);
}
public void setClientId(int clientId) {
this.clientId = clientId;
}
public int getClientId() {
return clientId;
}
public void setContent(String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
修 改异步接口的实现
public void sendMessage(int clientId, String message) {
ArrayList<HiMessage> messageList = clientMgr.getClient(clientId).getRoom().getMessageList();
messageList.add(new HiMessage(clientId, message));
}
@Override
public String[] updateMessage(int clientId, int lastIndex) {
ArrayList<HiMessage> messageList = clientMgr.getClient(clientId).getRoom().getMessageList();
if (lastIndex >= messageList.size()) {
return null;
}
String[] messageArray = new String[messageList.size() - lastIndex];
for (int i = lastIndex; i < messageList.size(); i++) {
HiMessage message = messageList.get(i);
String messageStr = "";
if (clientId == message.getClientId()) {
messageStr += "You:";
} else {
messageStr += "Stranger:";
}
messageStr += message.getContent();
messageArray[i - lastIndex] = messageStr;
}
return messageArray;
}
现 在已经能区分消息是谁发的了。不过还是有点丑,很明显客户端需要对消息数据做一些处理,现在我突然强烈怀疑返回纯字符串的接口设计。原本想即使要更改显示 的方式,也可以以HTML的方式返回纯字符串。啊,这让我想起了jsp,我不怎么喜欢这个。也许CS之间通信就应该只有数据本身,单纯的数据。改,让 updateMessage返回HiMessage[]类型。然后在客户端就可以得到消息的发布者的clientId,和自己的一对比就知道是自己发的, 还是别人发的。现在,客户端已经有能力自己规定如何显示消息了。也许是时候包装一下了。
创建了一个HiMessageUi类,继承 Composite,负责显示得到的消息,呃,前面的发信人最好换个颜色和字体,然后换一行再空出几个像素开始显示消息正文应该比较好。尝试了很久,利用 Chrome看了看Omegle和web qq的实现,发现GWT的接口不太够用了,什么padding之类的都没有,虽然也可以在Java代码里取得DOM对象进行操作,不过貌似GWT2.0有 了一种叫UiBinder的东西。趁机看了下,感觉还不错,决定用这个来做UI了。
创建UiBinder HiMessageUi
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
/* Add CSS here. See the GWT docs on UI Binder for more details */
.message {
padding: 5px;
}
.sender {
color: blue;
}
.content {
padding-left: 12px;
word-break: break-all;
word-wrap: break-word;
}
</ui:style>
<g:HTMLPanel styleName="{style.message}">
<g:HTML styleName="{style.sender}" ui:field="sender"/>
<g:HTML styleName="{style.content}" ui:field="content"/>
</g:HTMLPanel>
</ui:UiBinder>
private static HiMessageUiUiBinder uiBinder = GWT
.create(HiMessageUiUiBinder.class);
interface HiMessageUiUiBinder extends UiBinder<Widget, HiMessageUi> {
}
@UiField
HTML sender;
@UiField
HTML content;
public HiMessageUi(String sender, String content) {
initWidget(uiBinder.createAndBindUi(this));
// Can access @UiField after calling createAndBindUi
this.sender.setText(sender);
this.content.setText(content);
}
}
然后修改updateMessage
public void onSuccess(HiMessage[] result) {
if (result != null && result.length != 0) {
for (HiMessage message : result) {
if (message.getClientId() == clientId) {
contentPanel.add(new HiMessageUi("You:", message.getContent()));
} else {
contentPanel.add(new HiMessageUi("Stanger:", message.getContent()));
}
lastIndex++;
}
scrollPanel.scrollToBottom();
}
}
感觉还不错。索性彻底把Ui都改成UiBinder的方 式。
新建UiBinder HiChatUi
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
.important {
font-weight: bold;
}
</ui:style>
<g:HTMLPanel>
<g:DecoratorPanel>
<g:VerticalPanel>
<g:ScrollPanel width="500px" height="400px" ui:field="scrollPanel">
<g:VerticalPanel ui:field="contentPanel"/>
</g:ScrollPanel>
<g:TextArea width="500px" height="120px" ui:field="inputText"/>
</g:VerticalPanel>
</g:DecoratorPanel>
</g:HTMLPanel>
</ui:UiBinder>
再把原来的HelloUi里面相关的内容移到HiChatUi里面
private static HelloHiUiUiBinder uiBinder = GWT
.create(HelloHiUiUiBinder.class);
interface HelloHiUiUiBinder extends UiBinder<Widget, HiChatUi> {
}
@UiField
VerticalPanel contentPanel;
@UiField
TextArea inputText;
@UiField
ScrollPanel scrollPanel;
private int clientId = -1;
private HelloServiceAsync service = GWT.create(HelloService.class);
private int lastIndex = 0;
private Timer timer = new Timer() {
@Override
public void run() {
update();
}
};
public HiChatUi() {
initWidget(uiBinder.createAndBindUi(this));
timer.scheduleRepeating(2000);//ms
}
@UiHandler("inputText")
void onKeyPress(KeyPressEvent event) {
if (event.getCharCode() == KeyCodes.KEY_ENTER) {
sendMessage();
}
}
private void initClientId() {
service.getClientId(new AsyncCallback<Integer>() {
@Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
@Override
public void onSuccess(Integer result) {
clientId = result;
}
});
}
private void update() {
if (clientId == -1) {
initClientId();
} else {
service.updateMessage(clientId, lastIndex, new AsyncCallback<HiMessage[]>() {
@Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
@Override
public void onSuccess(HiMessage[] result) {
if (result != null && result.length != 0) {
for (HiMessage message : result) {
if (message.getClientId() == clientId) {
contentPanel.add(new HiMessageUi("You:", message.getContent()));
} else {
contentPanel.add(new HiMessageUi("Stanger:", message.getContent()));
}
lastIndex++;
}
scrollPanel.scrollToBottom();
}
}
});
}
}
private void sendMessage() {
String input = inputText.getText();
if (!input.isEmpty()) {
service.sendMessage(clientId, input, new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
@Override
public void onSuccess(Void result) {
inputText.setText("");
update();
}
});
}
}
}
实际上两个类区别并不大,不过一个是在构造函数里写代码画 Ui,另一个是在xml里面定义Ui,稍微直观一点罢了。原来的HelloUi可以删掉了。