我正在开发一个显示服务器数据的应用程序。服务器不是我的,它不是很稳定。连接太多会导致服务器崩溃。
我的主要活动中有一个到服务器的套接字,但有时我想打开读取数据并显示它的子活动。我的问题是我无法使用相同的套接字实现此功能,并且必须为每个活动打开一个新套接字。 每个活动都有一个线程,它从套接字读取并根据需要更新该活动的UI元素。
要在多个活动中使用相同的套接字,我尝试在开始新活动之前关闭活动的inputReader,但这只是让应用程序挂起。如果我将其保持打开状态,则新活动中的新线程永远不会收到任何数据。在开始新活动之前杀死线程是不可能的,因为线程通常被read()函数阻止。
无论如何,我有一个集中的线程来执行读取,然后将数据发送到其他活动中的所有其他线程,这样我就不必在每个活动中打开新的套接字了吗?
我觉得这是我要问的一个非常基本的问题,但我无法找到解决方案。
答案 0 :(得分:1)
基本上你自己回答了你的问题:
我可以有一个集中的线程来执行读取,然后将数据发送到其他活动中的所有其他线程。
意义:当然,这样的事情是可能的。但你必须坐下来,设计并实施它。首先,您应该定义一个合理的界面,允许您的其他线程与该中央服务进行沟通,例如:
WifiManager.NETWORK_STATE_CHANGED_ACTION
含义:不要让你的不同线程做“低级别”#34;谈到那个套接字,你创建一个抽象,让你说:"当我需要这种信息,然后我使用我的服务;它会给我一些具体的答案)。当然,这是一个非常通用的答案,但是,你的问题也不完全具体。
接下来的步骤是对该接口进行一些中心(可能是单例)实现;它在自己的线程上运行,并且可以由其他线程以同步的,明确定义的方式使用。
最后警告:如果您不拥有该服务器,并且低质量并且给您带来麻烦 - 不好建立。因为无论您在代码中执行什么操作,如果服务器做得不好,用户都会认为您的应用是问题所在。用户不关心操作是否因某些远程服务器崩溃而失败。所以你问题的另一个方面是:现在,你处在一个不好的地方。你应该花一些时间来寻找出路。否则,您将浪费很多的时间来为您正在处理的服务器构建变通方法。
答案 1 :(得分:1)
以下是一种非常简单明了的方法:
Service
,它在后台运行并通过套接字与服务器通信Service
从套接字接收数据并使用LocalBroadcastManager
BroadcastReceiver
并从Service
方法onReceive()
接收数据
醇>
要实现这一目标,您应该阅读Services和BroadcastReceivers的简介,以了解它们的工作原理。另外,为了首先获得基本概述,您应该阅读可用的App Components。
编辑,回答评论中的问题:
您可以随时致电Service
来停止stopService()
,但如果您不想要/需要Service
的所有功能,也可以采取不同的方式。您还可以创建一个与服务器进行通信的简单Service
或Thread
,而不是HandlerThread
。从Thread内部,您可以使用上面提到的技术(LocalBroadcastManager
)将数据转发/广播到您的活动。
只是给你一个基本结构的例子(虽然未经测试的代码):
class SocketThread implements Runnable
{
static final String SOCKET_DATA_RECEIVED = "com.your.package.SOCKET_DATA_RECEIVED";
static final String SOCKET_DATA_IDENTIFIER = "com.your.package.SOCKET_DATA";
private Context context;
SocketThread(Context c) {
context = c.getApplicationContext();
}
@Override
public void run() { // code running in your thread
// fetch data from socket ...
Intent intent = new Intent();
intent.putExtra(SOCKET_DATA_IDENTIFIER, data); // store data in your intent
// send data to registered receivers
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
// your code ...
}
}
然后您有了自己的活动,例如MyActivity1
,MyActivity2
,... MyActivityN
。他们都注册了嵌入式SocketDataReceiver
以接收由您的线程发送的广播意图SOCKET_DATA_RECEIVED
。
在onReceive()
方法中,您可以使用标识符intent
从SOCKET_DATA_IDENTIFIER
对象中提取数据。
public class MyActivity1 extends Activity
{
private SocketDataReceiver socketDataReceiver;
@Override
protected void onResume() {
super.onResume();
socketDataReceiver = new SocketDataReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(
socketDataReceiver, new IntentFilter(SocketThread.SOCKET_DATA_RECEIVED));
}
@Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(socketDataReceiver);
}
private class SocketDataReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent) {
// intent contains your socket data,
// get data from intent using SocketThread.SOCKET_DATA_IDENTIFIER
}
}
}