Home > Software design >  Dart enum extension isn't updating
Dart enum extension isn't updating

Time:04-07

I have the following code where I want to make sure my status will be localized in app, so I wanted to parse current locale and get value in needed language, but what it basically do, is simply remembering first language (locale) value parsed in it and staying with it till I restart my app

enum BillStatus {
  sent,
  processed,
  ...
}

extension BillStatusExtension on BillStatus {

  static Map<BillStatus, String> names = {
    BillStatus.sent: S.current.sent,
    BillStatus.processed: S.current.processed,
    ...
  };

  String? get name => names[this];
}

S.current means AppLocalizationDelegate provided with intl package

CodePudding user response:

When you do:

extension BillStatusExtension on BillStatus {
  static Map<BillStatus, String> names = {
    BillStatus.sent: S.current.sent,
    BillStatus.processed: S.current.processed,
    ...
  };

  String? get name => names[this];
}

You're creating a names Map that's lazily initialized with whatever the values are of S.current.sent, S.current.processed, etc. are at the time names is first accessed. When the locale changes, that Map will never be updated and still will be referencing the same String objects.

You should do one of:

  • Look up S.current.sent, S.current.processed, etc. dynamically. An easy way to do this would be to change your Map to store Functions instead of Strings:

    extension BillStatusExtension on BillStatus {
    
      static Map<BillStatus, String Function()> names = {
        BillStatus.sent: () => S.current.sent,
        BillStatus.processed: () => S.current.processed,
        ...
      };
    
      String? get name => names[this]?.call();
    }
    
  • Alternatively explicitly reinitialize the Map when the locale changes. This is more work and likely is overkill in this case, but it's a technique that you can use if recomputing values on every lookup is too expensive:

    extension BillStatusExtension on BillStatus {
    
      static Map<BillStatus, String> names = {};
      static String _lastLocale = '';
    
      static void _initializeNames() {
        names[BillStatus.sent] = S.current.sent;
        names[BillStatus.processed] = S.current.processed;
        ...
      }
    
      String? get name {
        if (locale != _lastLocale) {
          _initializeNames();
          _lastLocale = locale;
        }
        return names[this];
      }
    }
    

    Instead of reinitializing your Map lazily, you also could register a callback to do it immediately when the locale changes. See Is it possible to listen for system language change in Flutter?

CodePudding user response:

Your code should look like this:

void main() {
    final status = BillStatus.sent;
    print(status.name); // Sent
}

enum BillStatus { sent }

class BillStatusHelper {
  static const Map<BillStatus, String> names = {
    BillStatus.sent: 'Sent',
  };
}

extension BillStatusExtension on BillStatus {
  String get name => BillStatusHelper.names[this] ?? 'Unknown';
}
  • Related