Flutter Interview Handbook

GenUI & Adaptive UIs

100%

GenUI & Adaptive UIs

The next evolution of mobile interfaces combines Generative User Interfaces (GenUI)β€”where LLMs dynamically generate personalized UI layouts at runtimeβ€”with Adaptive UIs that seamlessly adjust across form factors (mobile, tablet, foldable, desktop, and web).


1. Generative UI (GenUI) Architecture

 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               1. User Prompt ("Show my expense breakdown")               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 β”‚ Mobile App UI  β”‚ ───────────────────────────────────────────────────────────────────────► β”‚ Gemini AI Modelβ”‚
 β””β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                                          β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                                                                                           β”‚
         β”‚ 4. Render Dynamic Widget Subtree                                                          β”‚ 2. Return JSON
         β”‚                                                                                           β”‚    Schema
 β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”                                                                                  β–Ό
 β”‚ Component      β”‚ β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
 β”‚ Registry       β”‚ 3. Validate & Map Schema -> Pre-tested Widgets
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

How GenUI Operates

  1. User Intent Query: User prompts the system (e.g. β€œShow my monthly spending by category as a pie chart with a breakdown list”).
  2. Structured LLM Output: The LLM (e.g. Gemini 1.5 Pro using responseSchema) generates a structured JSON payload defining UI components.
  3. Component Registry Mapping: The Flutter app validates the JSON and maps schema nodes to native, pre-tested Flutter widgets.

2. Secure Component Registry Pattern

Never execute arbitrary raw code strings generated by AI models! Instead, route JSON schemas through a strict, type-safe Component Registry:

typedef WidgetBuilderFunction = Widget Function(Map<String, dynamic> props);

class ComponentRegistry {
  static final Map<String, WidgetBuilderFunction> _registry = {
    'stat_card': (props) => StatCard(
      title: props['title'] ?? '',
      value: props['value'] ?? '',
      icon: props['icon'],
    ),
    'chart_pie': (props) => PieChartWidget(
      dataPoints: List<double>.from(props['data'] ?? []),
    ),
    'action_button': (props) => ElevatedButton(
      onPressed: () => handleAction(props['action']),
      child: Text(props['label'] ?? 'Action'),
    ),
  };

  static Widget render(Map<String, dynamic> json) {
    final String type = json['type'] ?? '';
    final builder = _registry[type];

    if (builder == null) {
      return const SizedBox.shrink(); // Fallback for unknown AI component types!
    }

    return builder(json['props'] ?? {});
  }
}

3. Multi-Form Factor Adaptive UIs

Flutter apps run across diverse screen sizes. Adaptive UIs adjust layout structures dynamically based on breakpoint constraints:

class AdaptiveScaffold extends StatelessWidget {
  final Widget body;
  final int selectedIndex;

  const AdaptiveScaffold({
    super.key,
    required this.body,
    required this.selectedIndex,
  });

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        // Desktop / Wide Screen: Show NavigationRail
        if (constraints.maxWidth >= 800) {
          return Scaffold(
            body: Row(
              children: [
                NavigationRail(
                  selectedIndex: selectedIndex,
                  destinations: const [
                    NavigationRailDestination(icon: Icon(Icons.home), label: Text('Home')),
                    NavigationRailDestination(icon: Icon(Icons.person), label: Text('Profile')),
                  ],
                ),
                Expanded(child: body),
              ],
            ),
          );
        }

        // Mobile Screen: Show BottomNavigationBar
        return Scaffold(
          body: body,
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: selectedIndex,
            items: const [
              BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
              BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
            ],
          ),
        );
      },
    );
  }
}

4. Trade-offs & Production Considerations

  • LLM Latency & Skeleton Loaders: Generating structured JSON via LLMs takes 500ms to 2s. Always display shimmer skeleton loaders while streaming or awaiting GenUI schemas.
  • Strict Schema Enforcement: Use Gemini’s responseSchema or OpenAPI JSON schemas to enforce valid LLM output structure, preventing missing field errors.