skip to Main Content

I am curious about how major top social media apps updating their UI without user interaction. I want to implement same in flutter mobile app. I have gone through dynamic feature (On-Demand feature in android)

Deferred Components

But, Don’t know do play store allow to upload only specific component.

If anyone have please help me.

2

Answers


  1. What you are looking for, are remote widgets and Server-Driven UI.

    Using Server-Driven UI and Remote Widgets in Flutter

    What is Server-Driven UI?

    Server-Driven UI is an approach where a server determines the structure and appearance of the user interface, dynamically sending instructions to the client at runtime on how to render it. This can be particularly useful in Flutter applications to achieve a more flexible and scalable UI.

    Implementing Server-Driven UI in Flutter

    To implement Server-Driven UI in Flutter, you can use the official rfw (Remote Flutter Widgets) package by flutter.dev.

    Firstly, create a .rfwtxt file with your remote widget that has the following structure:

    import core.widgets;
    import core.material;
    
    widget Counter = Scaffold(
      appBar: AppBar(title: Text(text: "Counter Demo")),
      body: Center(
        child: Column(
          mainAxisAlignment: "center",
          children: [
            Text(text: 'You have pushed the button this many times:', textAlign: "center"),
            Text(text: data.counter, style: {
              fontSize: 36.0,
            }),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: event "increment" { },
        tooltip: "Increment",
        child: Icon(icon: 0xE047, fontFamily: "MaterialIcons"),
      ),
    );
    

    Then, run encoder.dart in the directory of your .rfwtxt file to encode it into a .rfw file, which can than be used by the package (you need to adapt the file names accordingly).

    Next, prepare your runtime and download the previously created file within your code:

    import 'dart:io';
    
    import 'package:flutter/material.dart';
    import 'package:path/path.dart' as path;
    import 'package:path_provider/path_provider.dart';
    import 'package:rfw/rfw.dart';
    
    class _ExampleState extends State<Example> {
      final Runtime _runtime = Runtime();
      final DynamicContent _data = DynamicContent();
    
      final String url = "your/url/to/your/rfwfile"; // Change this to your server url
      bool _ready = false;
      int _counter = 0;
    
      @override
      void initState() {
        super.initState();
        _runtime.update(const LibraryName(<String>['core', 'widgets']), createCoreWidgets());
        _runtime.update(const LibraryName(<String>['core', 'material']), createMaterialWidgets());
        _updateData();
        _updateWidgets();
      }
    
      void _updateData() {
        _data.update('counter', _counter.toString());
      }
    
      Future<void> _updateWidgets() async {
        final Directory home = await getApplicationSupportDirectory();
        final File rfwFile = File(path.join(home.path, 'my_widget.rfw'));
        if (rfwFile.existsSync()) {
          try {
            _runtime.update(const LibraryName(<String>['main']), decodeLibraryBlob(await rfwFile.readAsBytes()));
            setState(() {
              _ready = true;
            });
          } catch (e, stack) {
            FlutterError.reportError(FlutterErrorDetails(exception: e, stack: stack));
          }
        }
        print('Fetching remote widget: $url'); // ignore: avoid_print
        final HttpClientResponse client = await (await HttpClient().getUrl(Uri.parse(url))).close(); // Download the file
        await rfwFile.writeAsBytes(await client.expand((List<int> chunk) => chunk).toList()); // Save the contents of the response to a local file
      }
    
      @override
      Widget build(BuildContext context) {
        Widget? result;
        if (_ready) {
          result = RemoteWidget(
            runtime: _runtime,
            data: _data,
            widget: const FullyQualifiedWidgetName(LibraryName(<String>['main']), 'Counter'),
            onEvent: (String name, DynamicMap arguments) {
              if (name == 'increment') {
                _counter += 1;
                _updateData();
              }
            },
          );
        }
        
        return result ?? Container();
      }
    }
    

    Limitations

    Once you realize that you can ship UI (and maybe logic, e.g. using
    Wasm; see the example below) you will slowly be tempted to move your
    whole application to this model.

    This won’t work.

    Flutter proper lets you create widgets for compelling UIs with
    gestures and animations and so forth. With RFW you can use those
    widgets, but it doesn’t let you create those widgets.

    For example, you don’t want to use RFW to create a UI that involves
    page transitions. You don’t want to use RFW to create new widgets that
    involve drag and drop. You don’t want to use RFW to create widgets
    that involve custom painters.

    Rather, RFW is best suited for interfaces made out of prebuilt
    components. For example, a database front-end could use this to
    describe bespoke UIs for editing different types of objects in the
    database. Message-of-the-day announcements could be built using this
    mechanism. Search interfaces could use this mechanism for rich result
    cards.

    RFW is well-suited for describing custom UIs from a potentially
    infinite set of UIs that could not possibly have been known when the
    application was created. On the other hand, updating the application’s
    look and feel, changing how navigation works in an application, or
    adding new features, are all changes that are best made in Flutter
    itself, creating a new application and shipping that through normal
    update channels.

    RFW is ideal for creating dynamic custom UIs with prebuilt components. However, it falls short in handling complex UI elements like gestures, animations, and custom painters. For fundamental UI changes, navigation adjustments, or new features, it’s recommended to utilize Flutter itself. RFW is best suited for adapting to unforeseen UI requirements within an evolving application.

    Conclusion

    This will fetch your .rfw file from your server at runtime, load it into your app and render it, allowing your application to dynamically adapt to server-side changes in the user interface. You could also implement code that periodically fetches the file from your database or listens for changes, so your UI stays up-to-date.

    For more information, refer to the docs.

    Login or Signup to reply.
  2. You can try shorebird to push app updates directly to users’ devices

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search