我认为这是一个很常见的问题,但我仍然没有找到满意的答案,所以我要问自己。
这是一段代码:
// this is insine OnClickView
TextView status = (TextView) findViewById(R.id.status);
status.setText("Trying to connect to the server...");
try {
// this opens a socket and send a login request to the server.
int result = CommunicationManager.login(String email, String password);
switch (result) {
case CommunicationManager.SUCCESS:
// login ok, go on with next screen
break;
case CommunicationManager.WRONG_EMAIL:
status.setTextColor(Color.RED);
status.setText("Wrong Email!");
break;
case CommunicationManager.WRONG_PASSWORD:
status.setTextColor(Color.RED);
status.setText("Wrong Password!");
break;
}
} catch (CommunicationException e) {
status.setTextColor(Color.RED);
status.setText("Unable to estabilish a connection!");
} catch (ProtocolException e) {
status.setTextColor(Color.RED);
status.setText("Protocol error!");
}
这就是我想要实现的目标:
- 用户点击发送按钮;
- status textview 显示“正在尝试连接到服务器...”;
- UI“等待”通信结束;
- status textview 相应地显示结果。
但是,当用户单击“发送”按钮时,UI 会冻结(奇怪的是在状态文本出现之前),直到通信完成(我尝试连接到未知主机)。一个快速的解决方法是设置套接字超时,但我不喜欢这种解决方案:UI 仍然冻结,应该设置哪个超时?
我的第一个想法显然是 Thread ,但是正如您所见,我需要返回一个 value,这在线程环境中没有多大意义,因为线程独立且异步运行。
所以我需要的绝对是 UI 等待服务执行但没有冻结。顺便说一句,在我看来,等待返回值意味着 UI必须等待任务结束,我只是不会让它冻结。
我遇到了 AsyncTask,但我看到了两个主要缺点:
- 在我看来,这与 UI 耦合太紧密了;
- 如果我想使用 Integer、String 和 Boolean 参数执行服务怎么办?我应该延长
AsyncTask<Object, Void, Void>
吗?
两者都导致不可扩展性。
我能做些什么来实现我的目标?请注意,对服务的另一个请求将是对尚未准备好的内容的请求,因此我应该每隔几次(假设十分钟)自动重复请求。所以可能我需要一些我可以使用的东西TimerTask
,但我仍然需要在每次执行该服务时向 UI 返回一个值(这样我可以更新状态文本并让用户知道发生了什么)。