1

我正在开发一个使用 Smack 库连接到 Openfire 服务器的 Android 应用程序。我有一个从 onStart() 方法调用 AsyncTask 以检索信息并将其添加到 UI 的活动。

AsyncTask 将使用 Smack MultiUserManager 类中的 getHostedRooms() 方法,遍历每个房间并从房间中获取 JID 值和主题字符串,并将该信息添加到哈希映射中。然后在 onPostExecute 方法中将该哈希映射返回给主线程。

我遇到的问题是异步任务通常不能提供所有正确的值。例如,有三个房间,通常它只会返回一两个的信息,有时会发送 null 而不是主题字符串。

当我调试代码并逐步完成它时,它每次都有效,所以我认为问题是不允许异步任务在全速运行时返回之前调用循环中的每一步。

有什么方法可以确保允许异步任务完成并按预期返回?我查看了 asynctask.get() 方法,但这似乎阻塞了 UI 线程。我已经复制了下面的 AsyncTask,如果您需要更多信息,请告诉我!

编辑:为了澄清,每次输入哈希映射的所有键值都是不同的

private class GetChatRoomData extends AsyncTask<Void, Void, HashMap<String, String>> {
    private Context context;
    private String username, password, returnMessage;
    private XMPPTCPConnection connection;
    private GetSubjectsCallBack callBack;

    private GetChatRoomData(User user, GetSubjectsCallBack callBack, Context context) {
        this.context = context;
        this.callBack = callBack;
        username = user.getUsername(); password = user.getPassword();
        returnMessage = "Subjects found";
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog.show();
    }

    @Override
    protected HashMap<String, String> doInBackground(Void... params) {
        XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
                .setUsernameAndPassword(username, password)
                .setServiceName(myservicename)
                .setHost("10.0.2.2")
                .setPort(5222).setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
                .build();

        HashMap<String, String> returnmap = new HashMap<String, String>();

        try {
            connection = new XMPPTCPConnection(config);
            connection.setPacketReplyTimeout(10000);
            connection.connect();
            connection.login(username, password);

            MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);
            List<HostedRoom> list = manager.getHostedRooms(myservicename);

            if(list.size() != 0) {
                for (HostedRoom room : list) {
                    String jid = room.getJid();
                    MultiUserChat tempMuc =
                            manager.getMultiUserChat(jid);
                    if (!(tempMuc.isJoined())) {
                        tempMuc.join(username);
                    }
                    String subject = tempMuc.getSubject();
                    returnmap.put(subject, jid);
                }
            } else {
                returnMessage = "No topics created yet";
            }

            connection.disconnect();

        } catch (Exception e) {
            returnMessage = "Could not connect";
        }

            return returnmap;
    }

    @Override
    protected void onPostExecute(HashMap<String, String> map) {
        progressDialog.dismiss();
        callBack.done(returnMessage, map);
        super.onPostExecute(map);
    }
}
4

1 回答 1

0

我找到了解决方案,将在此处发布以供将来使用。原来问题出在 for 循环中对 join() 的调用。有时在调用 getSubject() 之前不会建立连接,并且当这种情况发生时,主题返回为 null。如果这种情况发生多次,则将使用键“null”放入多个值,从而返回不完整的哈希映射。

我目前的解决方案是在 join() 之后调用 Thread.sleep() 以确保建立连接。如果无法建立连接,则会引发异常。可能不是最好的解决方案,但它有效。

于 2015-08-10T18:28:40.970 回答