Skip to content

LocalResources

LocalResources loads fragments and values from your Flutter app's asset bundle. It's the default resource provider and the right choice for apps that ship their entire UI inside the app binary.

When to Use

  • Your app ships with all fragments and value files as Flutter assets.
  • You don't need over-the-air UI updates.
  • You want analytics from XWidget Cloud but prefer to keep UI bundled (LocalResources.withAnalytics).

For cloud-delivered UI, see CloudResources.

Basic Usage

import 'package:xwidget/xwidget.dart';

import 'xwidget/generated/registry.g.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await XWidget.initialize(register: registerXWidgetComponents);

  runApp(MyApp());
}

XWidget.initialize() creates a default LocalResources when no resources argument is passed. Paths are read from XWidget.config, which is populated by the generated registry from your xwidget_config.yaml.

Explicit Instantiation

Pass an explicit LocalResources when you want to override paths or the asset bundle:

await XWidget.initialize(
  register: registerXWidgetComponents,
  resources: LocalResources(
    fragmentsPath: 'assets/ui/fragments',
    valuesPath: 'assets/ui/values',
  ),
);

Parameters

LocalResources({
  String? fragmentsPath,
  String? valuesPath,
  AssetBundle? assetBundle,
});
  • fragmentsPath — where fragment XML files live in the asset bundle. Defaults to XWidget.config.fragmentsPath (typically resources/fragments).
  • valuesPath — where value XML files live. Defaults to XWidget.config.valuesPath (typically resources/values).
  • assetBundle — the Flutter AssetBundle to read from. Defaults to rootBundle. Useful for testing with a TestAssetBundle or for apps that use a custom bundle.

With Cloud Analytics

LocalResources.withAnalytics keeps UI loading local but connects XWidget Cloud analytics. Fragment renders, errors, and navigation transitions flow to your analytics dashboard, but no bundle downloads happen.

await XWidget.initialize(
  register: registerXWidgetComponents,
  resources: LocalResources.withAnalytics(
    projectKey: '<your-project-key>',
    version: '1.0.0',
  ),
);

Parameters:

LocalResources.withAnalytics({
  required String projectKey,
  required String version,
  String? fragmentsPath,
  String? valuesPath,
  AssetBundle? assetBundle,
});
  • projectKey (required) — your XWidget Cloud project key. Get this from xc cloud project keys.
  • version (required) — the app version string. Reported with every analytics event. Typical value: the version from pubspec.yaml.
  • fragmentsPath, valuesPath, assetBundle — same as the default constructor.

The analytics channel is set to 'local' automatically so you can distinguish analytics from local-only versus cloud-delivered builds in your dashboards.

See Analytics for what gets tracked.

Testing

Pass a TestAssetBundle to load fragments and values from test fixtures:

testWidgets('home screen', (tester) async {
  final bundle = TestAssetBundle(...);  // your test fixtures

  await XWidget.initialize(
    register: registerXWidgetComponents,
    resources: LocalResources(
      fragmentsPath: 'test/fixtures/fragments',
      valuesPath: 'test/fixtures/values',
      assetBundle: bundle,
    ),
  );

  await tester.pumpWidget(
    MaterialApp(
      home: XWidget.inflateFragment('home', Dependencies()) as Widget,
    ),
  );

  expect(find.text('Welcome'), findsOneWidget);
});

Asset Registration

Fragments and values must be declared in pubspec.yaml under flutter.assets:

flutter:
  assets:
    - resources/fragments/
    - resources/values/

Subdirectories of the fragments folder must be listed explicitly (Flutter does not recurse):

flutter:
  assets:
    - resources/fragments/
    - resources/fragments/auth/
    - resources/fragments/settings/
    - resources/values/

See Resources for the full fragment / value directory convention.

Hot Reload

When you edit a fragment or value XML file during a Flutter debug session, the IDE plugins push the change to the running app via a debug service extension and LocalResources updates its bundles in place. The widget tree rebuilds from the root, but app state (controllers, dependencies, navigation) is preserved — no app restart needed.

See Hot Reload for how this works and IDE setup.