Browse Source

socketclient remove reconnect time

wr_202303
zsw 4 months ago
parent
commit
db76f9e15f
  1. 11
      assets/svg/shequn.svg
  2. 1
      lib/home/home_page.dart
  3. 73
      lib/im/SocketClient.dart
  4. 62
      lib/im/chat_details_page.dart
  5. 10
      lib/im/database/hx_database.dart
  6. 2
      lib/im/database/message.dart
  7. 72
      lib/im/im_view/im_page.dart
  8. 1
      lib/main_page.dart

11
assets/svg/shequn.svg

@ -1,14 +1,13 @@
<svg width="22.000000" height="22.000000" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg width="30.000000" height="30.000000" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<desc>
Created with Pixso.
</desc>
<defs>
<clipPath id="clip114_923">
<rect id="shequn" width="22.000000" height="22.000000" fill="white" fill-opacity="0"/>
<clipPath id="clip244_618">
<rect id="shequn-2" width="23.000000" height="23.000000" transform="translate(4.000000 4.000000)" fill="white" fill-opacity="0"/>
</clipPath>
</defs>
<g clip-path="url(#clip114_923)">
<path id="path" d="M13.69 14.75C12.4 15.71 11.05 16.56 9.63 17.32C8.21 18.07 6.75 18.72 5.24 19.26C5.45 19.41 5.67 19.55 5.89 19.68C6.11 19.81 6.34 19.93 6.57 20.04C6.8 20.16 7.04 20.26 7.28 20.36C7.52 20.45 7.77 20.54 8.01 20.61C8.26 20.69 8.51 20.76 8.76 20.82C9.01 20.87 9.27 20.92 9.52 20.96C9.78 21 10.03 21.02 10.29 21.04C10.55 21.06 10.81 21.07 11.07 21.07C11.33 21.06 11.58 21.05 11.84 21.03C12.1 21.01 12.35 20.98 12.61 20.94C12.87 20.89 13.12 20.84 13.37 20.78C13.62 20.72 13.87 20.65 14.11 20.57C14.36 20.49 14.6 20.4 14.84 20.3C15.08 20.2 15.32 20.1 15.55 19.98C15.78 19.86 16 19.74 16.22 19.6C16.44 19.47 16.66 19.33 16.87 19.18C17.08 19.02 17.28 18.87 17.48 18.7C17.68 18.53 17.87 18.36 18.05 18.18C18.24 18 18.42 17.81 18.59 17.61C18.76 17.42 18.92 17.22 19.07 17.01C19.23 16.8 19.37 16.59 19.51 16.37C19.65 16.16 19.78 15.93 19.9 15.7C20.02 15.47 20.13 15.24 20.24 15.01C20.34 14.77 20.43 14.53 20.52 14.28C20.6 14.04 20.68 13.79 20.74 13.54C20.81 13.29 20.87 13.04 20.91 12.79C20.96 12.53 20.99 12.28 21.02 12.02C21.05 11.76 21.06 11.5 21.07 11.24C21.08 10.99 21.07 10.73 21.06 10.47C21.05 10.21 21.02 9.95 20.99 9.7C20.96 9.44 20.92 9.19 20.86 8.93C20.81 8.68 20.75 8.43 20.68 8.18C19.68 9.44 18.59 10.62 17.42 11.72C16.25 12.82 15.01 13.83 13.69 14.75Z" fill="#32A060" fill-opacity="1.000000" fill-rule="nonzero"/>
<path id="path" d="M21.79 3.25C21.24 2.46 19.65 2.56 17.51 3.31C17.3 3.13 17.08 2.96 16.85 2.8C16.63 2.64 16.39 2.49 16.15 2.34C15.91 2.2 15.67 2.07 15.42 1.95C15.17 1.82 14.92 1.71 14.66 1.61C14.4 1.51 14.13 1.42 13.87 1.34C13.6 1.26 13.33 1.19 13.06 1.14C12.79 1.08 12.51 1.03 12.24 1C11.96 0.97 11.68 0.94 11.41 0.93C11.13 0.92 10.85 0.92 10.57 0.93C10.29 0.95 10.02 0.97 9.74 1C9.47 1.04 9.19 1.08 8.92 1.14C8.65 1.2 8.38 1.27 8.11 1.35C7.84 1.43 7.58 1.52 7.32 1.62C7.06 1.72 6.81 1.83 6.56 1.96C6.31 2.08 6.07 2.21 5.83 2.35C5.59 2.5 5.36 2.65 5.13 2.81C4.9 2.97 4.69 3.14 4.47 3.32C4.26 3.5 4.06 3.69 3.86 3.89C3.66 4.09 3.48 4.29 3.3 4.51C3.12 4.72 2.95 4.94 2.79 5.16C2.63 5.39 2.47 5.62 2.33 5.86C2.19 6.1 2.06 6.35 1.94 6.6C1.82 6.85 1.71 7.1 1.61 7.36C1.51 7.62 1.42 7.88 1.34 8.15C1.26 8.42 1.19 8.69 1.13 8.96C1.08 9.23 1.03 9.51 1 9.78C0.97 10.06 0.94 10.34 0.93 10.61C0.92 10.89 0.92 11.17 0.94 11.45C0.95 11.73 0.97 12 1.01 12.28C1.04 12.55 1.09 12.83 1.15 13.1C1.21 13.37 1.28 13.64 1.36 13.91C1.44 14.17 1.53 14.44 1.63 14.7C0.23 16.5 -0.35 17.97 0.2 18.73C1.36 20.36 7.14 18.21 13.1 13.93C19.07 9.64 22.95 4.87 21.79 3.25ZM10.15 9.83L9.18 11.07L8.64 9.6L7.44 8.64L8.91 8.12L9.87 6.89L10.39 8.36L11.62 9.33L10.15 9.83Z" fill="#32A060" fill-opacity="1.000000" fill-rule="nonzero"/>
<g clip-path="url(#clip244_618)">
<path id="path" d="M25.61 12.46C26.85 16.9 25.25 21.67 21.64 24.34C18 27.04 13.15 27.07 9.48 24.44C12.63 23.27 15.61 21.63 18.31 19.56C21.06 17.57 23.52 15.18 25.61 12.46ZM9.36 6.64C13.29 3.73 18.61 3.95 22.3 7.18C24.55 6.38 26.21 6.27 26.78 7.12C28 8.88 23.93 14.03 17.7 18.67C11.46 23.3 5.43 25.62 4.21 23.87C3.63 23.04 4.24 21.45 5.7 19.5C3.93 14.84 5.45 9.53 9.36 6.64ZM13.38 9.61C12.11 9.61 11.08 10.69 11.08 12.01C11.08 13.33 12.11 14.41 13.38 14.41C14.64 14.41 15.67 13.33 15.67 12.01C15.67 10.69 14.64 9.61 13.38 9.61Z" fill="#D8D8D8" fill-opacity="1.000000" fill-rule="nonzero"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

1
lib/home/home_page.dart

@ -855,4 +855,5 @@ class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
}

73
lib/im/SocketClient.dart

@ -20,6 +20,8 @@ class SocketClient {
final num port = 9090;
Socket _socket;
SharedPreferences _shared;
Timer timer;
bool get heartbeatActive => timer != null && timer.isActive;
connect() async {
_shared = await SharedPreferences.getInstance();
@ -41,17 +43,17 @@ class SocketClient {
print('收到来自:${dataResult.from},消息内容: ${utf8.decode(dataResult.data)} ');
Map<String, dynamic> messageMap = createMessage(userId, utf8.decode(dataResult.data), msgType: dataResult.type.value, userId: dataResult.from);
Message message = Message.fromJson(messageMap);
callbacks[userId]?.call(message); /// user self conversation list callback
if (callbacks[dataResult.from] != null) {
messageMap["state"] = 1;
message.state = 1;
callbacks[dataResult.from].call(message); /// user conversation callback
}
hxDatabase.insert(messageMap);
hxDatabase.insert(messageMap).then((value) {
messageMap["id"] = value;
Message message = Message.fromJson(messageMap);
if (callbacks[dataResult.from] != null) {
callbacks[dataResult.from].call(message); /// user conversation callback
}
callbacks[userId]?.call(message); /// user self conversation list callback
});
}, onError: (Object error, StackTrace stackTrace) {
debugPrint("socket-listen-error: $error, stackTrace: $stackTrace");
showDebugToast("socket-listen-error: $error, stackTrace: $stackTrace");
@ -69,9 +71,6 @@ class SocketClient {
_socket = null;
reconnect();
});
// checkConnect();
}
showDebugToast(text) {
@ -80,27 +79,53 @@ class SocketClient {
}
}
Proto heartbeatData() {
DateTime dateTime = DateTime.now();
int millisecondsTime = dateTime.millisecondsSinceEpoch;
Uint8List data = utf8.encode(jsonEncode({"heartbeat": millisecondsTime}));
MsgData msgData = MsgData(from: userId, type: MsgType.TEXT, data: data);
final proto2 = Proto(3, 1, msgData.writeToBuffer());
debugPrint("heartbeat: ${dateTime.toString()}");
return proto2;
}
heartbeat() {
Timer.periodic(const Duration(milliseconds: 30000), (timer) {
int millisecondsTime = DateTime.now().millisecondsSinceEpoch;
debugPrint("heartbeat: $millisecondsTime");
Uint8List data = utf8.encode(jsonEncode({"heartbeat": millisecondsTime}));
MsgData msgData = MsgData(from: userId, type: MsgType.TEXT, data: data);
final proto2 = Proto(3, 1, msgData.writeToBuffer());
cancelTimer();
timer = Timer.periodic(const Duration(milliseconds: 30000), (timer) {
if(!checkSocket()) {
timer.cancel();
return;
}
try {
_socket.add(proto2.toBytes());
} catch (e) {
debugPrint("socket-send-error: ${e.toString()}");
showDebugToast("socket-send-error: ${e.toString()}");
reconnect();
}
sendHeartBeatAndCheckSocket();
});
}
/// send heartBeat and check socket is connected
/// send error: reconnect,
/// else check Timer.periodic isActive ,
/// if not active: Timer.periodic send heartBeat
sendHeartBeatAndCheckSocket() {
final proto2 = heartbeatData();
try {
_socket.add(proto2.toBytes());
if (!socketClient.heartbeatActive) {
heartbeat();
debugPrint("socket-periodic-send-heart-beat");
}
} catch (e) {
debugPrint("socket-send-error: ${e.toString()}");
showDebugToast("socket-send-error: ${e.toString()}");
reconnect();
}
}
cancelTimer() {
if (timer != null && timer.isActive) {
timer.cancel();
timer = null;
}
}
reconnect() {
dispose();
connect();

62
lib/im/chat_details_page.dart

@ -89,8 +89,10 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
socketClient.addCallback(_toUser.mid, (Message message) {
messages.insert(0, message);
refreshState();
jumpToBottom();
messageShowTime().then((value) {
refreshState();
jumpToBottom();
});
});
refreshState();
jumpToBottom();
@ -105,6 +107,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
} else {
messages.addAll(messagePage);
}
await messageShowTime();
if (messagePage.isEmpty) {
refreshController.loadNoData();
return;
@ -114,6 +117,14 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
return Future.value();
}
Future messageShowTime() async {
List<Message> messagePages = await hxDatabase.queryTList(_toUser.mid);
for (var value in messages) {
Message message = messagePages.firstWhere((element) => value.id == element.id, orElse: () => null);
value.showTime = message != null;
}
}
///
queryUser() async {
final SharedPreferences value = await SharedPreferences.getInstance();
@ -123,10 +134,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
userInfo = UserInfo.fromJson(jsonDecode(value.getString('user')));
}
if (apiService == null)
apiService =
ApiService(Dio(), context: context, token: value.getString("token"));
BaseData<UserInfo> baseData =
await apiService.queryInfo().catchError((onError) {});
apiService = ApiService(Dio(), context: context, token: value.getString("token"));
BaseData<UserInfo> baseData = await apiService.queryInfo().catchError((onError) {});
if (baseData != null && baseData.isSuccess) {
setState(() {
userInfo = baseData.data;
@ -374,7 +383,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
child: SingleChildScrollView(
physics: BouncingScrollPhysics(),
controller: scrollController,
child: chatDetailsList()),
child: chatDetailsList(),
),
),
flex: 1,
),
@ -382,7 +392,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
],
),
),
));
),
);
}
///
@ -419,24 +430,25 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
),
child: Column(
children: [
Text(
// position == messages.length-1
// ?
AppUtils.milliTimeFormatter(DateTime.fromMillisecondsSinceEpoch(
int.parse(messages[position].time)))
// : AppUtils.getTimeDisplay(
// DateTime.fromMillisecondsSinceEpoch(
// int.parse(messages[position].time)),
// DateTime.fromMillisecondsSinceEpoch(
// int.parse(messages[position+1].time)))
,
textAlign: TextAlign.center,
style: TextStyle(
color: Color(0xFFA29E9E),
fontSize: 10.sp,
fontWeight: MyFontWeight.regular,
if (messages[position].showTime)
Text(
// position == messages.length-1
// ?
AppUtils.milliTimeFormatter(DateTime.fromMillisecondsSinceEpoch(
int.parse(messages[position].time)))
// : AppUtils.getTimeDisplay(
// DateTime.fromMillisecondsSinceEpoch(
// int.parse(messages[position].time)),
// DateTime.fromMillisecondsSinceEpoch(
// int.parse(messages[position+1].time)))
,
textAlign: TextAlign.center,
style: TextStyle(
color: Color(0xFFA29E9E),
fontSize: 10.sp,
fontWeight: MyFontWeight.regular,
),
),
),
// if (messages.indexOf(message) == (messages.length - 1))
// Padding(
// padding: EdgeInsets.only(top: 10.h, bottom: 24.h),

10
lib/im/database/hx_database.dart

@ -106,6 +106,16 @@ class HxDatabase {
});
}
Future<List<Message>> queryTList(userId) async{
await _dbIsOpen();
String sql = 'SELECT *, time / 300000 * 300000 AS time_interval FROM Message WHERE toId = ? OR fromId = ? GROUP BY time_interval ORDER BY time DESC';
return db.rawQuery(sql, [userId, userId]).then((value) {
return value.map((e) => Message.fromJson(e)).toList();
}, onError: (error) {
debugPrint("Messageerror: $error");
});
}
Future<Map<String, int>> messageUnreadCount(List<String> userIds, String selfUserId) async {
await _dbIsOpen();
String userStr = userIds.join(",");

2
lib/im/database/message.dart

@ -21,6 +21,8 @@ class Message {
int isDelete;
bool showTime = false;
Message(this.id, this.fromId, this.toId, this.replyId, this.content, this.attach, this.msgType, this.time, this.state, this.isDelete);
factory Message.fromJson(Map<String, dynamic> json) => Message(

72
lib/im/im_view/im_page.dart

@ -197,72 +197,6 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
if (mounted) setState(() {});
}
// queryMessage() async {
// BaseData<PageInfo<Message>> baseData = await apiService.msgList({
// "pageNum": pageNum,
// "pageSize": 10,
// "searchKey": "",
// "state": "",
// "typed": ""
// }).catchError((onError) {
// _refreshController.loadFailed();
// _refreshController.refreshFailed();
// });
//
// if (baseData != null && baseData.isSuccess) {
// if (pageNum == 1) {
// messages.clear();
// }
// List<Message> message = [];
// message.addAll(baseData.data.list);
// message.forEach((element) {
// if (element.typed == 2 || element.typed == 3) {
// messages.add(element);
// }
// });
// _refreshController.loadComplete();
// _refreshController.refreshCompleted();
// if (mounted) setState(() {});
// if (pageNum * 10 > int.tryParse(baseData.data.total)) {
// _refreshController.loadNoData();
// } else {
// pageNum += 1;
// }
// } else {
// _refreshController.loadFailed();
// _refreshController.refreshFailed();
// }
// }
// queryMsgStats() async {
// if (apiService == null) {
// SharedPreferences value = await SharedPreferences.getInstance();
// apiService = ApiService(
// Dio(),
// context: context,
// token: value.getString("token"),
// );
// }
// BaseData<List<MsgStats>> baseData = await apiService.stats().catchError((onError) {
// debugPrint("stats.error: $onError");
// });
// if (baseData != null && baseData.isSuccess) {
// setState(() {
// msgNumber.forEach((key, value) {
// msgNumber[key] = 0;
// });
// baseData.data.forEach((element) {
// if (msgNumber.containsKey(element.name)) {
// msgNumber[element.name] = element.number;
// }
// });
// });
// _refreshController.loadComplete();
// _refreshController.refreshCompleted();
// }
// EasyLoading.dismiss();
// }
///
queryMemberInfo(List<String> mids) async {
if (mids.isEmpty) {
@ -271,8 +205,10 @@ class _IMPage extends State<IMPage> implements OnChatMessage {
BaseData<List<ImUser>> baseData = await apiService.memberInfoByIds({
"mids": mids,
}).catchError((error) {
SmartDialog.showToast(AppUtils.dioErrorTypeToString(error.type),
alignment: Alignment.center);
SmartDialog.showToast(
AppUtils.dioErrorTypeToString(error.type),
alignment: Alignment.center,
);
});
if (baseData != null && baseData.isSuccess) {
if (baseData.data.isNotEmpty) {

1
lib/main_page.dart

@ -82,6 +82,7 @@ class _MainPage extends State<MainPage> with WidgetsBindingObserver {
break;
case AppLifecycleState.resumed: //
pushRoute();
socketClient.sendHeartBeatAndCheckSocket();
if (DateTime.now().millisecondsSinceEpoch - lastTime > 420000)
//**
// Navigator.of(context).popAndPushNamed('/router/start_page');

Loading…
Cancel
Save