tinode / dart-sdk

Dart SKD for using Tinode messenger in dart and flutter applications.
https://pub.dev/packages/tinode
Apache License 2.0
41 stars 20 forks source link

Tinode Connect and Disconnect Issue #11

Open cfanboy opened 3 years ago

cfanboy commented 3 years ago

Hi, I'm coming again. I initialized the Tincode as below codes on app startup:

if (tinode == null){
        tinode = Tinode(
            'Wow',
            ConnectionOptions(WebSocketUtils.WsUrl, WebSocketUtils.ApiKey, secure: true),
            ApiConstant.isDebug);
}

CtrlMessage connectResult = await tinode.connect();
if (connectResult.code < 300) {
  isConnect = true;
}

When the user logout, call the disconnect method and set the tinode instance to null:

disConnect() {
    tinode.disconnect();
    tinode = null;
}

But after the user signs in again, I re-call the initialization method, it throws the error:

Invalid argument(s): Object/factory with  type ConfigService is already registered inside GetIt. 
      throwIf (package:get_it/get_it_impl.dart:7:18)
#1      _GetItImplementation._register (package:get_it/get_it_impl.dart:800:5)
#2      _GetItImplementation.registerSingleton (package:get_it/get_it_impl.dart:585:5)
#3      Tinode._registerDependencies (package:tinode/tinode.dart:123:13)
#4      new Tinode (package:tinode/tinode.dart:114:5)
#5      WebSocketUtils.connectService (package:wow/pages/home/messages/websocket_utils.dart:37:18)
#6      WebSocketUtils.login (package:wow/pages/home/messages/websocket_utils.dart:54:13)
<asynchronous suspension>

I'm not sure what's problem is, is my disconnect not correct? Thanks

rxmoein commented 3 years ago

Hi, I updated the package, you can upgrade to version 1.0.0-alpha.4. It must work fine now.

rxmoein commented 3 years ago

You also don't need to create an instance every time. You can simply use disconnect and connect method.

cfanboy commented 3 years ago

Thanks. I updated and it's working.

Do you mean no need to set the tinode = null when calling disconnect every time?

rxmoein commented 3 years ago

Yes, you can keep the instance and just call disconnect and connect method

cfanboy commented 3 years ago

I tried only to call connect and disconnect this way before but hit a wired problem.

MyChats page list all users who chat with me. My initialize flow is:

  1. User login -> instance Tinode -> call connect
  2. Call IM tinode.loginToken to login -> Subscribe me topic
  3. On the User List page method initState, listen to messages:
    tinode.onMessage.listen((value) {
     // process received Meta message
    });
  4. Send the {get topic=me, what=sub} query to get all users.

If the app startup the first time, the tinode instance is null. It's working fine, can list the users who talked with me. Then I log out, calling tinode.disconnect, and login again, call connect method, wired thing happened, sometimes the send message very slowly, like loginToken costs over 3 seconds, and the message listener callback never working, I can see the IM Server response the query result {Meta} message, but app cannot go into onMessage method.

So I tried to set the tinode = null and found the above issue. Below is my WebSocketUtils codes:

class WebSocketUtils {
    static WebSocketUtils _singleton;
    Tinode tinode;
    static WebSocketUtils getInstance() {
        if (_singleton == null) {
        _singleton = new WebSocketUtils();
        }
        return _singleton;
    }

    connectService({String hostUrl}) async {
    try {
      if (tinode == null)
        tinode = Tinode(
            'Mitao',
            ConnectionOptions(WebSocketUtils.WsUrl, WebSocketUtils.ApiKey, secure: true),
            ApiConstant.isDebug);

      CtrlMessage connectResult = await tinode.connect();
      if (connectResult.code < 300) {
        isConnect = true;
      }
    } catch (error) {
      print(error);
    }
  }

  login() async {
    if (tinode == null || tinode.isConnected == false) {
      await connectService();
    }

    String imToken = await SharedPreferenceUtils.getValue(SharedPreferenceUtils.KEY_IM_TOKEN);
    CtrlMessage loginResult = await tinode.loginToken(imToken, null).then((value) {
      LogUtil.v(value);
      return value;
    }, onError: (error) {
      LogUtil.e(error);
      return null;
    });

    await tinode.subscribe("me", null, new SetParams()).then((value) {
      LogUtil.v(value);
      return value;
    }, onError: (error) {
      LogUtil.e(error);
      return null;
    });

    return loginResult;
  }

  disConnect() {
    tinode.disconnect();
  }
}
rxmoein commented 3 years ago

OK thank you for describing the problem I'll investigate this and see if I can find the problem. So for now let's initialize tinode each time you want to log in.

cfanboy commented 3 years ago

Ok, thank you again. ^_^

cfanboy commented 3 years ago

I just did testing. The messager listener as below did not work on the second the message sent.

var me = WebSocketUtils.getInstance().tinode.getMeTopic(); me.onSubsUpdated.listen((value) async { // Process received data }

sent: {"get":{"topic":"me","what":"sub","id":"115639"}}

rxmoein commented 3 years ago

Thanks I'll see what can I do