blob: 46e8434338c9a18cedceb97b15330a26db4ed9a0 [file] [log] [blame]
// Copyright 2014 The Flutter 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:async';
import 'system_channels.dart';
/// Manages the installation and loading of deferred components.
///
/// Deferred components allow Flutter applications to download precompiled AOT
/// dart code and assets at runtime, reducing the install size of apps and
/// avoiding installing unnecessary code/assets on end user devices. Common
/// use cases include deferring installation of advanced or infrequently
/// used features and limiting locale specific features to users of matching
/// locales. Deferred components can only deliver split off parts of the same
/// app that was built and installed on the device. It cannot load new code
/// written after the app is distributed.
///
/// Deferred components are currently an Android-only feature. The methods in
/// this class are a no-op and all assets and dart code are already available
/// without installation if called on other platforms.
class DeferredComponent {
// This class is not meant to be instantiated or extended; this constructor
// prevents instantiation and extension.
DeferredComponent._();
// TODO(garyq): We should eventually expand this to install components by loadingUnitId
// as well as componentName, but currently, loadingUnitId is opaque to the dart code
// so this is not possible. The API has been left flexible to allow adding
// loadingUnitId as a parameter.
/// Requests that an assets-only deferred component identified by the [componentName]
/// be downloaded and installed.
///
/// This method returns a Future<void> that will complete when the feature is
/// installed and any assets are ready to be used. When an error occurs, the
/// future will complete with an error.
///
/// This method should be used for asset-only deferred components or loading just
/// the assets from a component with both dart code and assets. Deferred components
/// containing dart code should call `loadLibrary()` on a deferred imported
/// library's prefix to ensure that the dart code is properly loaded as
/// `loadLibrary()` will provide the loading unit id needed for the dart
/// library loading process. For example:
///
/// ```dart
/// import 'split_component.dart' deferred as SplitComponent;
/// ...
/// SplitComponent.loadLibrary();
/// ```
///
/// This method will not load associated dart libraries contained in the component,
/// though it will download the files necessary and subsequent calls to `loadLibrary()`
/// to load will complete faster.
///
/// Assets installed by this method may be accessed in the same way as any other
/// local asset by providing a string path to the asset.
///
/// See also:
///
/// * [uninstallDeferredComponent], a method to request the uninstall of a component.
/// * [loadLibrary](https://api.dart.dev/dart-mirrors/LibraryDependencyMirror/loadLibrary.html),
/// the dart method to trigger the installation of the corresponding deferred component that
/// contains the dart library.
static Future<void> installDeferredComponent({required String componentName}) async {
await SystemChannels.deferredComponent.invokeMethod<void>(
'installDeferredComponent',
<String, dynamic>{ 'loadingUnitId': -1, 'componentName': componentName },
);
}
/// Requests that a deferred component identified by the [componentName] be
/// uninstalled.
///
/// Since uninstallation typically requires significant disk i/o, this method only
/// signals the intent to uninstall. Completion of the returned future indicates
/// that the request to uninstall has been registered. Actual uninstallation (e.g.,
/// removal of assets and files) may occur at a later time. However, once uninstallation
/// is requested, the deferred component should not be used anymore until
/// [installDeferredComponent] or `loadLibrary()` is called again.
///
/// It is safe to request an uninstall when dart code from the component is in use,
/// but assets from the component should not be used once the component uninstall is
/// requested. The dart code will remain usable in the app's current session but
/// is not guaranteed to work in future sessions.
///
/// See also:
///
/// * [installDeferredComponent], a method to install asset-only components.
/// * [loadLibrary](https://api.dart.dev/dart-mirrors/LibraryDependencyMirror/loadLibrary.html),
/// the dart method to trigger the installation of the corresponding deferred component that
/// contains the dart library.
static Future<void> uninstallDeferredComponent({required String componentName}) async {
await SystemChannels.deferredComponent.invokeMethod<void>(
'uninstallDeferredComponent',
<String, dynamic>{ 'loadingUnitId': -1, 'componentName': componentName },
);
}
}