blob: d68ede5de8f20333b9a1efcf95998ee31e7da9ee [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert' show json;
import 'package:fidl_fuchsia_modular/fidl.dart';
import 'package:lib.app.dart/logging.dart';
import 'package:lib.widgets/modular.dart';
/// The [ModuleModel] implementation for this project, which encapsulates how
/// this module interacts with the Modular framework.
///
/// There are three methods that you can override, as shown in the code below.
///
/// * [onReady]: This method is called when [Module.initialized()] is called by
/// the framework. You must call [super.onReady()] method, and you can do any
/// additional initialization work needed for this module.
///
/// * [onStop]: This method is called when [Lifecycle.terminate()] is called by
/// the framework. You must clean up any resources, close any FIDL channels,
/// and call [super.onStop()] method.
///
/// * [onNotify]: This method can be overriden, when you want to process change
/// notifications coming from the [Link] service. In this example, we read the
/// counter value from the json, and notify all the listeners so that they can
/// refresh the UI with the new data.
///
/// In the example code below, the counter value is stored in [Link], which is a
/// synchronized, persistent data storage provided by the Modular framework.
/// [Link] stores data in JSON format, so the data should be properly encoded /
/// decoded, when setting and retrieving data.
///
/// Storing this value in [Link] has a few implications.
///
/// * When this module is running in the same story on multiple devices, any
/// changes to counter value on any device is seen by other devices. That is,
/// the [onNotify()] method will be called on all instances of this module and
/// they would be able to update the UI accordingly.
///
/// * The value is persisted and be restored across reboot. When cloudsync is
/// enabled on Fuchsia, the value will be restored correctly even on a
/// previously unused device.
///
/// For other states that are not needed to be synchronized or persisted (e.g.,
/// transient UI states, animation states) can be stored in a `State` of a
/// `StatefulWidget`, as in normal Flutter applications.
class __ProjectName__ModuleModel extends ModuleModel {
/// Creates a new instance.
///
/// Setting the [watchAll] value to `true` makes sure that you get notified
/// by [Link] service, even with the changes are made by this model.
__ProjectName__ModuleModel() : super(watchAll: true);
int _counter = 0;
/// Gets and sets the counter value.
int get counter => _counter;
set counter(int value) {
_counter = value;
// This call notifies all the listeners that something has been changed in
// this data model. The ScopedModelDescendant widget with this model class
// as the type parameter (see: home_page.dart) automatically becomes a
// listener of this model class. Therefore, this notifyListeners() call
// makes sure that the UI is correctly updated with the new counter value.
notifyListeners();
}
/// Increments the counter value and writes the new value to the link.
void incrementCounter() {
// This method does not increment the _counter value directly, to maintain a
// uni-directional flow and treat the Link value as the source of truth.
// The onNotify() method will be called by Link with the new value, and we
// only update the _counter value in response to that notification.
//
// This is important for correctly restoring the counter value and keeping
// it in sync with other devices.
link.set(<String>['counter'], json.encode(counter + 1));
}
@override
void onReady(
ModuleContext moduleContext,
Link link,
) {
super.onReady(moduleContext, link);
// Do more initialization here.
}
@override
void onStop() {
// Do any clean-up work as necessary here.
super.onStop();
}
@override
void onNotify(String encodedJson) {
// Process any data change notification from the Link.
log.info('Link data changed: $encodedJson');
dynamic decodedJson = json.decode(encodedJson);
if (decodedJson is Map<String, dynamic> && decodedJson['counter'] is int) {
counter = decodedJson['counter'];
}
}
}