Closed endison1986 closed 1 year ago
@endison1986 I tested example/lib/chat2.dart in iOS environment. It is very smooth. Could you please send to code fragment to me to identify the problem and tell me which platform you tested?
@robert-luoqing thanks for reply and I apologize for not carrying more information I test in Android environment,MIUI 10.3.2 basic Android 9, but I don't have an Apple developer account, so I never tested in iOS environment.
MessageDetailView.dart
const MessageDetailView({super.key});
@override
Widget build(BuildContext context) {
return SafeArea(
child: GetBuilder<MessageDetailState>(
init: MessageDetailState(context),
builder: (state) {
var theme = state.theme;
return Scaffold(
backgroundColor: theme.primaryColorDark,
bottomNavigationBar: _buildBottomNavigationBar(state),
appBar: _buildAppBar(state),
body: _buildMessageDetailList(state),
);
},
),
);
}
_buildMessageDetailList(MessageDetailState state) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 30.w, vertical: 24.h),
child: EasyRefresh(
controller: state.easyRefreshController,
footer: ClassicalFooter(),
child: FlutterListView(
reverse: true,
physics: const BouncingScrollPhysics(),
controller: state.listViewController,
delegate: FlutterListViewDelegate(
(BuildContext context, int index) => _buildTextMessageDetail(state, index),
childCount: state.messageCount,
onItemKey: (index) => state.messageList[index].id.toString(),
keepPosition: false,
initOffsetBasedOnBottom: true,
firstItemAlign: FirstItemAlign.end,
),
),
onLoad: state.doLoadAction,
),
);
}
Widget _buildTextMessageDetail(MessageDetailState state, int index) {
final message = state.messageList[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Center(
child: Text(
formatMessageTime(message),
style: state.theme.lightTextStyle,
),
),
Container(
padding: EdgeInsets.all(24.h),
margin: EdgeInsets.symmetric(vertical: 18.h),
decoration: BoxDecoration(color: state.theme.backgroundColor, borderRadius: const BorderRadius.all(Radius.circular(6.66))),
child: state.renderMessageContent(message),
)
],
);
}
MessageDetailState.dart
@override
onInit() {
super.onInit();
subscription = layoutState.eventBus.on<SaveMessagePayload>().listen((event) {
if (event.appId == currentMessageDetail.app.appId) {
update();
jumpToLast();
}
});
}
@override
onReady() {
super.onReady();
jumpToLast();
}
jumpToLast() {
listViewController.sliverController.jumpToIndex(0);
}
Future<void> doLoadAction() async {
currentMessageDetail.loadHistory().then((value) {
update();
easyRefreshController.finishLoad(success: true, noMore: value <= 10);
});
}
I tested char2.dart, as you say, it's smooth.
I have simplify your code into https://github.com/robert-luoqing/flutter_list_view/blob/master/example/lib/chat3.dart. But I still can' reproduce your issue. I doubt you misuse the getx state to empty messageList then set messageList again
@robert-luoqing thanks for your help.
I tested for a long time, and I found the reason. because I use StyledText.selectable(styled_text: ^5.1.0
) to create content widget, and this widget caused the above problems.
Widget renderMessageContent(Message message) {
// ....
return StyledText.selectable(
text: '11111'
}
}
These codes alone can cause lag
but I only use ListView and jumpTo, this problem never occur, Is there anything that can be optimized
Please add onIsPermanent: (keyOrIndex) => true) into FlutterListViewDelegate to resolve the issue.
delegate: FlutterListViewDelegate(
(BuildContext context, int index) => _buildTextMessageDetail(index),
childCount: messageList.length,
onItemKey: (index) => messageList[index]["id"],
keepPosition: false,
initOffsetBasedOnBottom: true,
firstItemAlign: FirstItemAlign.end,
onIsPermanent: (keyOrIndex) => true),
The issue caused by the first item is always generating a new render and StyledText.selectable will cause two renders, the first render height and second render height is different.
Thank you very mush @robert-bitguild and @robert-luoqing , It works. 非常感谢
But I have a new problem, and looks like it.
when I use onIsPermanent: (keyOrIndex) => true
in the widget, the old problem fixed, but when I drag the message list and to load history message, when I insert message into the message list, the problem occur again.
But old code is works when I load history message.
Future<void> doLoadAction() async {
currentMessageDetail.loadHistory().then((value) {
update();
easyRefreshController.finishLoad(success: true, noMore: value <= 10);
});
}
Future<int> loadHistory() async {
if (messageSize == 0) return 0;
final last = messageList.last;
final historyCount = await messageProvider.getHistoryMessageCount(appId, 10, last.id);
if (historyCount > 0) {
final historyMessage = await messageProvider.getMessageList(appId, 10, last.id);
for (var element in historyMessage) {
_messageList.add(element);
}
}
return historyCount;
}
without onIsPermanent: (keyOrIndex) => true
with onIsPermanent: (keyOrIndex) => true
I can't reproduce your issue when I mockup your code. Please change some code in below to reproduce your issue and send me back.
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_list_view/flutter_list_view.dart';
import 'package:styled_text/styled_text.dart';
class Chat3 extends StatefulWidget {
const Chat3({Key? key}) : super(key: key);
@override
State<Chat3> createState() => _Chat3State();
}
class _Chat3State extends State<Chat3> {
final easyRefreshController = EasyRefreshController();
final listViewController = FlutterListViewController();
var messageList = <Map<String, dynamic>>[];
_generateMsg() {
var time = DateTime.now();
var newMsg = {
"id": time.microsecondsSinceEpoch.toString(),
"time": time.toString(),
"msg": time.toString()
};
messageList.insert(0, newMsg);
setState(() {});
}
_generateMsgs() {
var time = DateTime.now();
for (int i = 0; i < 10; i++) {
time = time.add(const Duration(milliseconds: 1));
var newMsg = {
"id": time.microsecondsSinceEpoch.toString(),
"time": time.toString(),
"msg": time.toString()
};
messageList.add(newMsg);
}
}
@override
void initState() {
_generateMsgs();
super.initState();
}
Future<void> doLoadAction() async {
await Future.delayed(const Duration(seconds: 1));
_generateMsgs();
easyRefreshController.finishLoad(success: true, noMore: false);
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Chat"),
actions: [
TextButton(
onPressed: _generateMsg,
child: const Text(
"Mock To Receive",
style: TextStyle(color: Colors.white),
))
],
),
body: _buildMessageDetailList(),
);
}
_buildMessageDetailList() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 24),
child: EasyRefresh(
controller: easyRefreshController,
footer: ClassicalFooter(),
child: FlutterListView(
reverse: true,
physics: const BouncingScrollPhysics(),
controller: listViewController,
delegate: FlutterListViewDelegate(
(BuildContext context, int index) => _buildTextMessageDetail(index),
childCount: messageList.length,
onItemKey: (index) => messageList[index]["id"],
keepPosition: false,
initOffsetBasedOnBottom: true,
firstItemAlign: FirstItemAlign.end,
onIsPermanent: (key) => true,
),
),
onLoad: doLoadAction,
),
);
}
Widget _buildTextMessageDetail(int index) {
final message = messageList[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: StyledText.selectable(text: message["time"].toString()),
),
Container(
padding: const EdgeInsets.all(24),
margin: const EdgeInsets.symmetric(vertical: 18),
decoration: const BoxDecoration(
color: Colors.yellow,
borderRadius: BorderRadius.all(Radius.circular(6.66))),
child: StyledText.selectable(text: message["msg"]),
)
],
);
}
}
first, very thanks for this project, I try to implement chat view, and load message from the top down, but I failure, some problems always occur with me. I use your project and implement chat functional basically. but when I create a new chat view, and send message one by one, the chat view always has a brief flicker and the animation is not very smooth, I don't known how to config can avoid this problem, help me please.