Благодаря советам @pskink мне удалось заставить мой CustomPainter непрерывно перерисовываться, хотя он все еще не идеален.
См. dart / flutter: CustomPaint обновляется с меньшей скоростью, чем обновление значения ValueNotifier
Поскольку в текущем решении все еще существует проблема с частотой обновления, я просто кратко сообщаю о том, что у меня есть:
Мне в основном нужно создать уведомитель и назначить ffi -получено значение для него в нужном месте с помощью опроса.
// in initState() of State class
_notifier = ValueNotifier<NativeColor>(ffiGetColor().ref);
...
// in a timer method
_notifier.value = ffiGetColor().ref;
Затем с помощью CustomPaint
привяжите уведомитель к перерисовке в его конструкторе
@override
Widget build(BuildContext context) {
return Container(
...
child: CustomPaint(
painter: _ColorViewPainter(
context: context,
notifier: _notifier,
...
)
)
);
}
class _ColorViewPainter extends CustomPainter {
ValueNotifier<NativeColor> notifier;
BuildContext context;
Color clrBackground;
_ColorViewPainter({this.context, this.notifier, this.clrBackground})
: super(repaint: notifier) {
}
@override
bool shouldRepaint(_ColorViewPainter old) {
print('should repaint');
return true;
}
@override
void paint(Canvas canvas, Size size) {
print("paint: start");
final r = notifier.value.r;
final g = notifier.value.g;
final b = notifier.value.b;
print("color: $r, $g, $b");
final paint = Paint()
..strokeJoin = StrokeJoin.round
..strokeWidth = 1.0
..color = Color.fromARGB(255, r, g, b)
..style = PaintingStyle.fill;
final width = size.width;
final height = size.height;
final content = Offset(0.0, 0.0) & Size(width, height);
canvas.drawRect(content, paint);
print("paint: end");
}
}
GOTCHAS
ValueNotifier
полагается на следующее, чтобы иметь возможность запускать уведомление для своих слушателей
- Тип значения, к которому он привязан, определил
operator ==
ValueNotifier
поле значения, к которому привязывается интересующий объект данных, явно переназначается с НОВЫМ объектом данных при изменениях.
Это очень важно, когда мы привязываем уведомитель к пользовательский класс, Wi th, который мы должны
- Перегрузить его
operator ==
. - Назначить новый объект
ValueNotifier<MyClass>.value
вместо вызова обычных методов текущего объекта для изменения значения.
В противном случае CustomPaint
paint()
не будет вызываться при желаемых изменениях.
В качестве другого примера, этот настраиваемый класс не подходит для связывания с ValueNotifier
, потому что там не перегружен operator==
:
class MyClass {
int prop = 0;
void changeValue(newValue) {
prop = newValue;
}
}
В качестве другого примера предположим, что у нас есть собственный класс:
class MyClass {
int prop = 0;
@override
bool operator ==(covariant MyClass other) {
return other is MyClass && prop != other. prop;
}
void changeValue(newValue) {
prop = newValue;
}
}
Это будет работать:
class _MyViewState extends State<MyView> {
ValueNotifier<MyClass> notifier;
Timer _timer;
....
@override
initState() {
super.initState();
notifier = ValueNotifier<MyClass>(MyClass());
_timer = Timer.periodic(Duration(milliseconds: 10), _updateData);
}
_updateData(Timer t) {
var myObj = MyClass(newValue);
notifier.value = myObj;
}
}
Но это не сработает.
class _MyViewState extends State<MyView> {
ValueNotifier<MyClass> notifier;
Timer _timer;
....
@override
initState() {
super.initState();
notifier = ValueNotifier<MyClass>(MyClass());
_timer = Timer.periodic(Duration(milliseconds: 10), _updateData);
}
_updateData(Timer t) {
var newValue = getNewValueSomewhere();
notifier.value.changeValue(newValue);
}