Mobiele ontwikkeling met Flutter · Les

Remote config, feature flags en gefaseerde releases

Schakel functies op afstand in en voer wijzigingen geleidelijk uit zonder de app opnieuw in te dienen.

Les 4 van 413 stappen

Remote config, feature flags en gefaseerde releases is een gratis Mobiele ontwikkeling met Flutter-les op CoddyKit. Dit is les 4 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Mobiele ontwikkeling met Flutter. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Mobiele ontwikkeling met Flutter bevat in totaal 4 lessen.

Waarom configuratie op afstand

Beoordelingscycli van appstores duren lang. Als een functie defect wordt uitgebracht, kan het dagen duren voordat een hotfix gebruikers bereikt. Configuratie op afstand ontkoppelt de code uitbrengen van de functie inschakelen.

  • Functievlaggen schermen codepaden af met een boolean die je vanaf een server beheert.
  • Configuratie op afstand levert instelbare waarden (tekenreeksen, getallen, JSON) zonder nieuwe build.
  • Gefaseerde uitrol stelt een wijziging bloot aan een steeds groter percentage gebruikers.

In Flutter is firebase_remote_config het gebruikelijke hulpmiddel, maar dezelfde patronen gelden voor LaunchDarkly, ConfigCat of je eigen backend.

Een vlag lokaal modelleren

Voordat je een SDK koppelt, modelleer je vlaggen als gewone Dart, zodat de rest van de app nooit rechtstreeks met tekenreeksen werkt. Een getypeerd configuratieobject maakt standaardwaarden expliciet en zorgt dat de code te testen is.

Dit is pure Dart met verstandige ingebouwde standaardwaarden — precies wat je uitbrengt als het netwerk niet beschikbaar is.

class AppConfig {
  final bool newCheckoutEnabled;
  final int maxUploadMb;
  final String welcomeMessage;

  const AppConfig({
    this.newCheckoutEnabled = false,
    this.maxUploadMb = 10,
    this.welcomeMessage = 'Welcome!',
  });
}

void main() {
  const defaults = AppConfig();
  print('checkout: ${defaults.newCheckoutEnabled}');
  print('maxUploadMb: ${defaults.maxUploadMb}');
  print('welcome: ${defaults.welcomeMessage}');
}

Firebase Remote Config instellen

Als Firebase is geïnitialiseerd, haal je de singleton FirebaseRemoteConfig op, stel je standaardwaarden in de app in en configureer je het ophaalgedrag via RemoteConfigSettings.

  • fetchTimeout begrenst hoelang het ophalen wacht.
  • minimumFetchInterval beperkt het aantal keer ophalen om quota te respecteren. Gebruik een kleine waarde tijdens het debuggen en uren in productie.

Standaardwaarden zorgen ervoor dat de app zich vóór de eerste geslaagde ophaalactie voorspelbaar gedraagt.

import 'package:firebase_remote_config/firebase_remote_config.dart';

Future<FirebaseRemoteConfig> initRemoteConfig() async {
  final rc = FirebaseRemoteConfig.instance;

  await rc.setConfigSettings(RemoteConfigSettings(
    fetchTimeout: const Duration(seconds: 10),
    minimumFetchInterval: const Duration(hours: 6),
  ));

  await rc.setDefaults(const {
    'new_checkout_enabled': false,
    'max_upload_mb': 10,
    'welcome_message': 'Welcome!',
  });

  return rc;
}

Ophalen en activeren

Remote Config scheidt ophalen (waarden downloaden naar een lokale cache) van activeren (de opgehaalde waarden actief maken). De gemaksfunctie fetchAndActivate() doet beide en geeft terug of er nieuwe waarden zijn geactiveerd.

Pak de aanroep altijd af: bij een netwerkfout moet je terugvallen op de laatst geactiveerde waarden of je standaardwaarden in de app — laat nooit het opstartpad crashen.

Future<void> refreshConfig(FirebaseRemoteConfig rc) async {
  try {
    final updated = await rc.fetchAndActivate();
    if (updated) {
      // New values are now live; rebuild dependent UI.
      print('Remote config activated with new values');
    }
  } catch (e) {
    // Offline or quota hit: keep last-known-good values.
    print('Remote config fetch failed, using cached/defaults: $e');
  }
}

Getypeerde waarden lezen

Remote Config slaat intern alles op als tekenreeksen, maar biedt getypeerde getters: getBool, getInt, getDouble, getString. Zet ze terug om naar je AppConfig, zodat de rest van de app getypeerd blijft.

Centraliseer deze omzetting op één plek. Als een sleutelnaam verandert, hoef je die maar één keer aan te passen.

import 'package:firebase_remote_config/firebase_remote_config.dart';

AppConfig readConfig(FirebaseRemoteConfig rc) {
  return AppConfig(
    newCheckoutEnabled: rc.getBool('new_checkout_enabled'),
    maxUploadMb: rc.getInt('max_upload_mb'),
    welcomeMessage: rc.getString('welcome_message'),
  );
}

UI achter een vlag afschermen

Een functievlag hoort één beslispunt te bewaken. Lees de vlag één keer bovenaan in de widgetstructuur (of vanuit een provider) en maak daar een vertakking.

Houd de afscherming oppervlakkig: vertak op basis van de vlag, niet diep in de bedrijfslogica, zodat je de vlag later eenvoudig kunt verwijderen.

Widget buildCheckout(BuildContext context, AppConfig config) {
  if (config.newCheckoutEnabled) {
    return const NewCheckoutScreen();
  }
  return const LegacyCheckoutScreen();
}

Configuratie met JSON-waarde parsen

Voor uitgebreidere gegevens kun je een JSON-tekenreeks in één sleutel opslaan en decoderen. Zo kan één vlag een volledig gestructureerd experiment bevatten — thema's, drempelwaarden, geordende lijsten — zonder tientallen sleutels toe te voegen.

Hieronder staat zelfstandige Dart die het patroon voor decoderen en terugvallen laat zien dat je zou toepassen op rc.getString('promo_banner').

import 'dart:convert';

class PromoBanner {
  final String text;
  final int priority;
  PromoBanner(this.text, this.priority);
}

PromoBanner parsePromo(String raw) {
  try {
    final map = jsonDecode(raw) as Map<String, dynamic>;
    return PromoBanner(
      map['text'] as String? ?? '',
      map['priority'] as int? ?? 0,
    );
  } catch (_) {
    return PromoBanner('', 0); // malformed JSON -> safe default
  }
}

void main() {
  final ok = parsePromo('{"text":"Summer Sale","priority":5}');
  print('${ok.text} (${ok.priority})');
  final bad = parsePromo('not-json');
  print('fallback text empty: ${bad.text.isEmpty}');
}

Gefaseerde uitrol op percentage

Bij een gefaseerde uitrol stel je een functie bijvoorbeeld bloot aan 1% van de gebruikers, daarna aan 10%, 50% en 100% — terwijl je bij elke stap crash- en metriekdashboards in de gaten houdt. Firebase Remote Config doet dit aan de serverkant met percentagevoorwaarden op basis van een stabiele, willekeurige gebruikersbucket.

De belangrijkste vereiste: het indelen in buckets moet stabiel zijn. Een gebruiker die aan de uitrol is toegewezen, moet daarin blijven tijdens verschillende sessies; anders knippert de UI en zijn de metrieken betekenisloos.

Stabiele bucketing aan de clientkant

Als je in plaats van Firebase een eigen backend uitrolt, implementeer je de bucketing aan de clientkant. Hash een stabiele gebruikers-id naar een waarde in [0, 100) en vergelijk die met de uitroldrempel. Dezelfde id komt altijd in dezelfde bucket terecht.

Deze deterministische hashing vormt de kern van gefaseerde uitrol en A/B-verdelingen.

int bucketOf(String userId) {
  // Simple stable hash -> 0..99
  var hash = 0;
  for (final code in userId.codeUnits) {
    hash = (hash * 31 + code) & 0x7fffffff;
  }
  return hash % 100;
}

bool isInRollout(String userId, int percent) {
  return bucketOf(userId) < percent;
}

void main() {
  const id = 'user-42';
  print('bucket: ${bucketOf(id)}');
  print('in 10% rollout: ${isInRollout(id, 10)}');
  print('stable on retry: ${bucketOf(id) == bucketOf(id)}');
}

Uitschakelknoppen en veilige standaardwaarden

De waardevolste vlag is een uitschakelknop: een boolean op afstand waarmee je een risicovolle functie onmiddellijk uitschakelt zonder een release. Twee regels maken uitschakelknoppen betrouwbaar:

  • De veilige toestand moet de standaardwaarde zijn. Een uitschakelknop hoort standaard false te zijn (functie uit), zodat een mislukte ophaalactie nooit per ongeluk het risicovolle pad inschakelt.
  • Lees de vlag elke keer op het beslispunt, niet één keer bij het opstarten, zodat het omschakelen ervan effect heeft bij de volgende configuratievernieuwing.

Plan voor Remote Config een vernieuwing bij het hervatten van de app, zodat een uitschakelknop binnen één cyclus op de voorgrond wordt doorgegeven.

// Default OFF => a fetch failure leaves the risky feature disabled.
bool experimentalSyncEnabled(AppConfig config) {
  return config.newCheckoutEnabled; // example risky path
}

void onAppResumed(FirebaseRemoteConfig rc) {
  // Re-fetch so a flipped kill switch reaches the user quickly.
  refreshConfig(rc);
}

Luisteren naar realtime-updates

Nieuwere versies van Firebase Remote Config ondersteunen realtime-updates: een stream die wordt geactiveerd wanneer de server nieuwe waarden publiceert, zodat je niet hoeft te wachten op de volgende geplande ophaalactie. Je moet nog steeds activate() aanroepen om ze actief te maken.

Gebruik dit voor uitschakelknoppen waarbij minuten ertoe doen. Combineer de listener met setState/provider-invalidatie om getroffen widgets opnieuw op te bouwen.

import 'package:firebase_remote_config/firebase_remote_config.dart';

void subscribeToUpdates(FirebaseRemoteConfig rc, void Function() onChanged) {
  rc.onConfigUpdated.listen((event) async {
    await rc.activate();
    onChanged(); // e.g. trigger a UI rebuild
  });
}

Korte controle

Test je begrip van een veilig uitrolontwerp.

Samenvatting

Je hebt geleerd hoe je functies uitgeschakeld uitbrengt en op afstand beheert:

  • Modelleer vlaggen als een getypeerde AppConfig met expliciete standaardwaarden.
  • Initialiseer Remote Config met setDefaults en afgestemde RemoteConfigSettings, en voer daarna defensief fetchAndActivate() uit.
  • Lees getypeerde waarden en scherm de UI af op één oppervlakkig beslispunt; geef uitgebreide gegevens door als JSON-tekenreeksen.
  • Voer gefaseerde uitrollen uit met stabiele bucketing op basis van percentages, zodat gebruikers consequent wel of niet deelnemen.
  • Laat elke uitschakelknop standaard in de veilige toestand staan en gebruik realtime-updates plus vernieuwing bij hervatten, zodat wijzigingen snel worden doorgegeven.

Samen zorgen deze technieken ervoor dat je implementatie en release van elkaar kunt loskoppelen en op incidenten kunt reageren zonder een ronde langs de appstore.

Gratis beginnen

Leer Dart met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
22
Lessen
88

Veelgestelde vragen

Is de les “Remote config, feature flags en gefaseerde releases” gratis?

Ja — je kunt hier op het web alle 3 lessen van het leerpad Mobiele ontwikkeling met Flutter, waaronder “Remote config, feature flags en gefaseerde releases”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Mobiele ontwikkeling met Flutter bevat in totaal 4 lessen.

Wat leer ik in “Remote config, feature flags en gefaseerde releases”?

Schakel functies op afstand in en voer wijzigingen geleidelijk uit zonder de app opnieuw in te dienen. Je oefent met Mobiele ontwikkeling met Flutter door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Mobiele ontwikkeling met Flutter te beginnen?

Ervaring vooraf is niet nodig. Mobiele ontwikkeling met Flutter op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.

Hoe lang duurt de les “Remote config, feature flags en gefaseerde releases”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Mobiele ontwikkeling met Flutter?

Ja. Elke les over Mobiele ontwikkeling met Flutter bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Buildflavors en omgevingsconfiguratie
  2. Geautomatiseerde pijplijnen met Fastlane en GitHub Actions
  3. Crashrapportage en gesymboliceerde stacktraces
  4. Remote config, feature flags en gefaseerde releases
← Terug naar Mobiele ontwikkeling met Flutter