Mobilutveckling med Flutter · Lektion

Fjärrkonfiguration, funktionsflaggor och stegvisa utrullningar

Växla funktioner på distans och rulla ut ändringar gradvis utan att skicka in appen på nytt.

Lektion 4 av 413 steg

Fjärrkonfiguration, funktionsflaggor och stegvisa utrullningar är en gratis lektion i Mobilutveckling med Flutter på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Mobilutveckling med Flutter, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Mobilutveckling med Flutter innehåller totalt 4 lektioner.

Varför fjärrkonfiguration

Granskningen i appbutiker tar tid. Om en funktion skickas ut trasig kan det dröja flera dagar innan en snabbkorrigering når användarna. Fjärrkonfiguration frikopplar leveransen av koden från aktiveringen av den.

  • Funktionsflaggor styr åtkomsten till kodvägar med hjälp av en boolesk variabel som du kontrollerar från en server.
  • Fjärrkonfiguration levererar justerbara värden (strängar, tal, JSON) utan en ny build.
  • Stegvisa utrullningar gör en ändring synlig för en växande andel användare.

I Flutter är firebase_remote_config det vanligaste verktyget, men samma mönster gäller för LaunchDarkly, ConfigCat eller din egen backend.

Modellera en flagga lokalt

Innan du kopplar in något SDK bör du modellera flaggorna som vanlig Dart, så att resten av appen aldrig hanterar råa strängar. Ett typat konfigurationsobjekt gör standardvärdena tydliga och koden testbar.

Det här är ren Dart med rimliga standardvärden inbyggda — exakt det du skickar ut om nätverket inte är tillgängligt.

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}');
}

Konfigurera Firebase Remote Config

När Firebase har initierats hämtar du singleton-instansen FirebaseRemoteConfig, anger standardvärden i appen och konfigurerar hämtningsbeteendet via RemoteConfigSettings.

  • fetchTimeout begränsar hur länge en hämtning väntar.
  • minimumFetchInterval begränsar hur ofta hämtningar görs för att respektera kvoter. Använd ett litet värde i debug-läge och flera timmar i produktion.

Standardvärden garanterar att appen fungerar på ett rimligt sätt innan den första lyckade hämtningen.

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;
}

Hämta och aktivera

Remote Config skiljer mellan hämtning (ladda ner värden till en lokal cache) och aktivering (göra de hämtade värdena aktiva). Bekvämlighetsmetoden fetchAndActivate() gör båda delarna och returnerar om nya värden aktiverades.

Omslut alltid anropet: ett nätverksfel ska falla tillbaka på de senast aktiverade värdena eller standardvärdena i appen — startflödet får aldrig krascha.

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');
  }
}

Läs typade värden

Remote Config lagrar allt som strängar internt men tillhandahåller typade getters: getBool, getInt, getDouble, getString. Mappa tillbaka dem till din AppConfig så att resten av appen förblir typad.

Samla denna mappning på ett enda ställe. Om ett nyckelnamn ändras behöver du då bara rätta det en gång.

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'),
  );
}

Styr UI med en flagga

En funktionsflagga bör skydda en enda beslutspunkt. Läs den en gång nära toppen av widgetträdet (eller från en provider) och välj sedan gren.

Håll styrningen ytlig: välj gren utifrån flaggan, inte djupt inne i affärslogiken, så att flaggan senare kan tas bort genom en ren radering.

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

Parsa JSON-baserad konfiguration

För mer omfattande nyttolaster kan du lagra en JSON-sträng i en enda nyckel och avkoda den. Då kan en flagga bära ett helt strukturerat experiment — teman, tröskelvärden, sorterade listor — utan att du behöver lägga till dussintals nycklar.

Nedan visas fristående Dart som demonstrerar mönstret för avkodning och reservvärde, vilket du skulle använda för 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}');
}

Stegvis utrullning i procent

En stegvis utrullning gör en funktion tillgänglig för exempelvis 1 % av användarna, sedan 10 %, 50 % och slutligen 100 % — samtidigt som du följer krasch- och mätvärdespaneler vid varje steg. Firebase Remote Config gör detta på serversidan med procentvillkor baserade på en stabil, slumpmässigt tilldelad användargrupp.

Det viktigaste kravet är att grupperingen måste vara stabil. En användare som tilldelats utrullningen måste förbli med i den mellan sessioner, annars flimrar gränssnittet och mätvärdena saknar betydelse.

Stabil gruppering på klientsidan

Om du använder en egen backend i stället för Firebase implementerar du grupperingen på klientsidan. Hasha ett stabilt användar-ID till ett värde i [0, 100) och jämför det med utrullningströskeln. Samma ID hamnar alltid i samma grupp.

Denna deterministiska hashing är kärnan i stegvisa utrullningar och A/B-delningar.

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)}');
}

Avstängningsknappar och säkra standardvärden

Den mest värdefulla flaggan är en avstängningsknapp: en boolesk fjärrinställning som omedelbart inaktiverar en riskfylld funktion utan en ny release. Två regler gör avstängningsknappar tillförlitliga:

  • Det säkra läget måste vara standard. En avstängningsknapp bör ha false som standard (funktionen avstängd), så att en misslyckad hämtning aldrig råkar aktivera den riskfyllda kodvägen.
  • Läs flaggan vid beslutspunkten varje gång, inte bara vid uppstart, så att en ändring börjar gälla vid nästa konfigurationsuppdatering.

För Remote Config bör du schemalägga en uppdatering när appen återupptas, så att en avstängningsknapp sprids inom en enda förgrundscykel.

// 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);
}

Lyssna efter uppdateringar i realtid

Nyare versioner av Firebase Remote Config stöder uppdateringar i realtid: en ström som aktiveras när servern publicerar nya värden, så att du inte behöver vänta på nästa schemalagda hämtning. Du måste fortfarande anropa activate() för att göra dem aktiva.

Använd detta för avstängningsknappar när minuter spelar roll. Kombinera lyssnaren med setState/ogiltigförklaring av provider för att bygga om berörda widgets.

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
  });
}

Snabbkontroll

Testa dina kunskaper om säker design för utrullningar.

Sammanfattning

Du har lärt dig att leverera funktioner inaktiverade och styra dem på distans:

  • Modellera flaggor som en typad AppConfig med tydliga standardvärden.
  • Initiera Remote Config med setDefaults och finjusterade RemoteConfigSettings, och kör sedan fetchAndActivate() med defensiv felhantering.
  • Läs typade värden och styr UI vid en enda ytlig beslutspunkt; hantera omfattande nyttolaster som JSON-strängar.
  • Genomför stegvisa utrullningar med stabil procentbaserad gruppering så att användare konsekvent hamnar med eller utan funktionen.
  • Låt varje avstängningsknapp ha sitt säkra läge som standard och använd uppdateringar i realtid samt uppdatering när appen återupptas, så att ändringar sprids snabbt.

Tillsammans gör detta att du kan frikoppla distribution från release och hantera incidenter utan en ny vända genom appbutiken.

Gratis att börja

Lär dig Dart med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
22
Lektioner
88

Vanliga frågor

Är lektionen ”Fjärrkonfiguration, funktionsflaggor och stegvisa utrullningar” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Mobilutveckling med Flutter, inklusive ”Fjärrkonfiguration, funktionsflaggor och stegvisa utrullningar”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Mobilutveckling med Flutter innehåller totalt 4 lektioner.

Vad lär jag mig i ”Fjärrkonfiguration, funktionsflaggor och stegvisa utrullningar”?

Växla funktioner på distans och rulla ut ändringar gradvis utan att skicka in appen på nytt. Ni övar på Mobilutveckling med Flutter med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Mobilutveckling med Flutter?

Du behöver inga förkunskaper. Utbildningen i Mobilutveckling med Flutter på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Fjärrkonfiguration, funktionsflaggor och stegvisa utrullningar”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Mobilutveckling med Flutter-lektionen?

Ja. Varje Mobilutveckling med Flutter-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Byggvarianter och miljökonfiguration
  2. Automatiserade pipelines med Fastlane och GitHub Actions
  3. Kraschrapportering och symboliserade stacktraces
  4. Fjärrkonfiguration, funktionsflaggor och stegvisa utrullningar
← Tillbaka till Mobilutveckling med Flutter