Reputation: 105
I am new to flutter and I think I miss understand the Widgets lifecycle and what is feasible. I use Riverpod for state management and Service creation.
I am building a widget to display a stream of logs coming from a LogManager. It will display an history of logs (currentLogs) and every time a new log is added to the stream, it should display in my Widget.
You can see below that I use SelectableText.rich and TextSpan, the reason is that I style each TextSpan differently depending on the log it represents but I still want to be able to select text across different TextSpan (Styling stuff removed here for readability).
import 'package:bulo_ui/core/connect/model/server_config.dart';
import 'package:bulo_ui/core/log/model/log.dart';
import 'package:bulo_ui/core/log/providers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:rxdart/rxdart.dart';
class LogStreamWidget extends ConsumerWidget {
final Server? server;
Stream<Log>? _logStream;
List<Log> _logs = [];
LogStreamWidget(this.server);
@override
Widget build(BuildContext context, WidgetRef ref) {
final logManager = ref.read(logManagerProvider(server));
// Concatenate existing logs + stream of new logs.
final currentLogsStream = Stream.fromIterable(logManager.currentLogs);
_logStream = Rx.concat([currentLogsStream, logManager.newLogStream]);
_logs = List.from(logManager.currentLogs);
return Container(
child: StreamBuilder<Log>(
stream: _logStream,
builder: (context, snapshot) {
if (snapshot.hasData) {
// Append the new log to the log list
_logs.add(snapshot.data!);
}
return SelectableText.rich(
TextSpan(
children: _logs.map((log) {
return (TextSpan(text: "${log.timeStr} ${log.msg}\n"));
}).toList(),
),
);
},
),
);
}
}
With the current implementation, my selection of text in the widget is erased every time a new log is added to the stream. That's very annoying / not user friendly, imagine a log every 1s, you finish to select a piece of the logs that you have to do it again.....
I think this happens because whenever the stream _logStream
have a new data, the entire SelectableText.rich widget rebuild. So the selected text in the TextSpan widgets disappear and redraw.
I believe I need to find a way to use the stream to APPEND children to a Widget like Column without rebuilding it and its existing children. This does not seems to fit how Flutter and the WidgetTree works, so maybe there is another solution?
But yeah, basically need to dynamically add widgets / TextSpan to a list already displayed without redrawing the previous TextSpan objects.
Many thanks to the community for your help!
Upvotes: 1
Views: 67