应用程序IncomingHandler有时不接收Service消息

时间:2016-11-05 18:31:48

标签: java android multithreading socket.io android-service

我正在构建Android应用程序,我正在努力处理重新连接。

所以流程是这样的:
 1.连接您已经拥有的令牌  2.用户通过socket.io
连接到服务器  2.a)你有活跃的令牌
      - 来自server的积极响应=>大家都很开心  2.b)您没有令牌或令牌不在数据库中       - 你必须从另一台服务器获得新令牌
      - 提出了新的要求       - 作为响应,用户正在尝试再次连接

现在代码:

应用

主要功能我正在运行以确保所有内容都已连接

public static boolean isSocketConnected = false; //declared in AndroidApplication
public static boolean isServiceBound = false;     //declared in AndroidApplication
public volatile boolean allowNextSocketConnection = true; //declared in same calss as _runMePlease_

private void runMePlease() { //running in new thread
  if (AndroidApplication.isServiceBound) {
            if (AndroidApplication.isSocketConnected) {
                allowNextSocketConnection = false;
                connected = true;
                Logger.log("WE ARE CONNECTED");
            } else {
                if(isNetworkAvailable()){
                        if(allowNextSocketConnection) {
                            allowNextSocketConnection = false;
                            AndroidApplication.sendDataToService(CONNECT);
                        } else {
                            Logger.log("WAITING FOR SERVICE RESPONSE");
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        runMePlease();
                }
  }

这就是我在新令牌到来之后正在运行的内容:

public void setSocketNewToken(){
    AndroidApplication.isSocketConnected = false;
    allowNextSocketConnection = true;
}

这是在连接成功后运行的:

public void setSocketConnected(){
    Logger.log("SOCKET CONNECTED");
    AndroidApplication.isSocketConnected = true;
}

第一次运行时一切运行顺畅,如果我杀死服务器并快速重新连接。但是只有在令牌过期和重新连接之后,有时它才会连接或者它正在连接但仍然循环通过“等待服务响应”并且它不应该因为我们已经有 isSocketConnected 真的。

有什么想法吗?

修改

在输入大量日志之后,我现在可以看到 runMePlease()正在运行,我正在接收来自服务的更新并且它没有运行 IncomingHandler

AndroidApplication片段(在实现AtomicBoolean之后)

static class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case CONNECTED:
                    Logger.log("New connect");
                    isSocketConnected.set(true);
                    connectionManager.setSocketConnected();
                    break;
                case DISCONNECTED:
                    Logger.log("Disconnect");
                    connectionManager.setSocketDisconnected();
                    break;
                case REFRESH_TOKEN:
                    Logger.log("Refresh token");
                    new Thread("Try2Connect") {
                        @Override
                        public void run() {
                            getNewToken();
                        }
                    }.start();

                    break;
                default:
                    super.handleMessage(msg);
            }
        }

服务代码段

public Emitter.Listener connected = new Emitter.Listener() {
    @Override
    public void call(Object... args) {
        Logger.log("CONNECT!!!!!!!!!");
        messengerSynchronizer.sendToApplication(CONNECTED, ""); // sending data back to AndroidApplication
    }
};

所以基本上在我运行 runMePlease()之后,等待 Logger.log(“等待服务响应”); 响应记录在 Emit.Listener已连接但AndroidApplication未运行 CONNECTED 块代码。
因此,在重新运行 runMePlease()之后,它首次正常工作,它的循环没有任何结束的可能性。

1 个答案:

答案 0 :(得分:2)

我还没有查看详细的流程,但是当您从不同的线程访问isSocketConnectedisServiceBound时,您必须声明它们volatile,以便所有写入都是从另一个线程读取它们时立即可见。否则,线程可能会读取这些变量的缓存值,即使它们已在另一个线程中已更改。

此外,如果您有多个可以调用runMePlease()的线程,那么对allowNextSocketConnection使用AtomicBoolean是有意义的,否则使用以下代码

if(allowNextSocketConnection) {
    allowNextSocketConnection = false;
    // ...
ifallowNextSocketConnection时,

两个帖子可以输入true。为了防止这种情况,您可以使用compareAndSet(boolean expect, boolean update)方法,这样只有一个线程可以进入if