Как игнорировать состояние с локтем во флаттере?

Я использую cubit для управления состоянием виджетов, и я хочу, чтобы виджет обновлялся только тогда, когда испускается определенный тип состояния.

part of 'TestData.dart';

@immutable
abstract class TestState {}

class TestInitial extends TestState {}

class TestValueUpdated extends TestState {
  TestValueUpdated(this.message);
  
  final String message;

  @override
  bool operator ==(Object other) {
    return other is TestValueUpdated && other.message == message;
  }

  @override
  int get hashCode => message.hashCode;
}

class TestScaleUpdated extends TestState {
  TestScaleUpdated(this.message);

  final String message;

  @override
  bool operator ==(Object other) {
    return other is TestScaleUpdated && other.message == message;
  }

  @override
  int get hashCode => message.hashCode;
}

Я создал класс состояний с именем TestState, и этот класс в настоящее время имеет 3 состояния: начальное, значение обновлено, масштаб обновлен.

class TestData extends Cubit<TestState> {

//Codes here

  Future<void> keepPlayStatus() async {
    emit(TestValueUpdated(getTimeStamp()+" / "+getMaxTime()+"  |  "+getPosition()));
  }

  Future<void> updateScaleValueMessage() async {
    emit(TestScaleUpdated((size * 100).round().toInt().toString() + " %"));
  }
}

и этот класс с именем TestData использует TestState и расширяет Cubit.

В основном, когда пользователь обновляет значение масштабирования, зажимая экран, этот класс будет выдавать состояние TestScaleUpdated, а когда пользователь что-то играет, он будет выдавать состояние TestValueUpdated.

и в пользовательском интерфейсе

//somewhere of the codes, called widget A
child: BlocBuilder<TestData, TestState>(
  builder: (context, state) {
    if(state is TestValueUpdated) {
      return Text(
        state.message,
        textAlign: TextAlign.end,
        style: TextStyle(color: ThemeManager.getRGBfromHex(0x514745)),
      );
    } else {
      return Text(
        "00:00.000 / 00:04.800 | 1.1.1",
        textAlign: TextAlign.end,
        style: TextStyle(color: ThemeManager.getRGBfromHex(0x514745)),
      );
    }
  },
)

//the other part of the codes, called widget B
child: BlocBuilder<TestData, TestState>(
  builder: (context, state) {
    if(state is TestScaleUpdated) {
      return Text(
        state.message,
        textAlign: TextAlign.center,
        style: TextStyle(color: ThemeManager.getRGBfromHex(0x514745)) ,
      );
    } else {
      return Text(
        "100 %",
        textAlign: TextAlign.center,
        style: TextStyle(color: ThemeManager.getRGBfromHex(0x514745)) ,
      );
    }
  },
)

Я пробовал этот код. Эти 2 виджета обновляют свой статус, когда TestData выдает какое-то состояние. Проблема для этого кода заключается в том, что, если пользователь что-то играет, поскольку состояние TestScaleUpdated не будет отправлено, статус виджета B возвращается в исходное состояние, всегда показывая 100%.

Если пользователь обновляет масштаб, то TestValueUpdated не будет выдаваться, поэтому виджет A всегда будет иметь начальное состояние, показывающее 00: 00.000 / 00: 04.800 | 1.1.1.

Итак, сейчас я хочу сделать так, чтобы виджет игнорировал обновление статуса. Например, в конструкторе BlocBuilder

(context, state) {
  if(state is TestScaleUpdated) {
    return Text("Scale!");
  else if(state is TestInitial) {
    return Text("Initial!");
  } else {
    //ignore, or keep widget's status
  }
}

Проблема здесь, если я объясню более подробно, заключается в следующем: предположим, что пользователь что-то сыграл, поэтому текст виджета A изменится на 00:10.000 / 00:40.000 | 2.0.0.

Затем, когда пользователь пытается изменить значение масштаба, это влияет не только на виджет B, но и на виджет A. Но поскольку TestData испускает только TestScaleUpdated состояние, текст виджета A возвращается к 00:00.000 | 00:04.800 | 1.1.1, в то время как он должен сохранить свой текст и статус.

Я хочу, чтобы при отправке TestScaleUpdated обновлялся только виджет B, а при отправке TestValueUpdated обновлялся только виджет A. Просто управление 2 или более виджетами по-разному с помощью одного класса cubit.

Должен ли я объединить эти 2 состояния: TestScaleUpdated и TestValueUpdated в одно состояние, содержащее 2 message для каждого виджета?

или я могу сохранить статус виджета, если испущенное состояние не удовлетворяет определенному условию?


person Mandarin Smell    schedule 20.05.2021    source источник


Ответы (1)


Я бы создал одно государство, в котором есть вся необходимая информация. Но если вы просто хотите, чтобы виджеты перестраивались только в определенных ситуациях, вы можете сделать это для своего виджета A следующим образом:

BlocBuilder<TestData, TestState>(
  buildWhen: (oldState, newState) => newState is TestValueUpdated;
  builder: (context, state) {
      return Text(
        state is TestValueUpdated ? state.message : "00:00.000 / 00:04.800 | 1.1.1",
        textAlign: TextAlign.end,
        style: TextStyle(color: ThemeManager.getRGBfromHex(0x514745)),
      );
  },
)
person Mäddin    schedule 20.05.2021
comment
Умм, мне надо подробнее объяснить ситуацию. Предположим, что текст виджета A был 00:10:000 / 00:40.000 | 2.0.0. Но затем, когда пользователь изменяет масштаб, текст виджета A возвращается к 00:00.000 / 00:04.800 | 1.1.1, в то время как он должен сохранять свое время и числа. Я хочу, чтобы обновлялся только виджет B, когда состояние TestScaleUpdated испускается. Я могу объединить 2 состояния в 1 состояние, содержащее все необходимые данные как для виджета A, так и для виджета B, но я не хочу создавать ненужные данные. Является ли объединение состояний единственным способом сделать одно, содержащее все данные? - person Mandarin Smell; 20.05.2021
comment
Слияние состояний полезно, но, возможно, этого достаточно для реализации моего вышеупомянутого решения, поскольку виджет A затем перестраивается, например, только тогда, когда состояние изменяется соответствующим образом. Но я бы сделал и то, и другое: реализовал функцию buildWhen для BlocBuilder и имел состояние, в котором хранятся все необходимые данные. - person Mäddin; 20.05.2021
comment
Ой, извини, я видел buildWhen сейчас. Да, я хотел такую ​​вещь. Большое спасибо, я приму твой ответ - person Mandarin Smell; 20.05.2021