docs: warn that checkForUpdate/update make network calls (#311)
Users sometimes gate app startup on checkForUpdate() or update() completing (e.g. awaiting in initState before showing content), which can cause the app to appear stuck on the splash screen when the network is slow. Add warning doc comments to both methods recommending the .then() pattern for startup code, and update README examples to use .then(). Fixes https://github.com/shorebirdtech/shorebird/issues/3179
This commit is contained in:
@@ -37,58 +37,43 @@ flutter pub add shorebird_code_push
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
After adding the package to your `pubspec.yaml`, you can use it in your app like
|
Shorebird automatically checks for and downloads updates in the background.
|
||||||
this:
|
Most apps do not need this package. This package is for apps that want
|
||||||
|
additional control, such as displaying update status to the user or prompting
|
||||||
|
before downloading.
|
||||||
|
|
||||||
|
**Important:** `checkForUpdate()` and `update()` make network calls that may
|
||||||
|
be slow. Avoid gating app startup on the result (e.g. awaiting in `initState`),
|
||||||
|
as the app may appear stuck on the splash screen. Use `.then()` instead.
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
// Import the library
|
|
||||||
import 'package:shorebird_code_push/shorebird_code_push.dart';
|
import 'package:shorebird_code_push/shorebird_code_push.dart';
|
||||||
|
|
||||||
// Launch your app
|
|
||||||
void main() => runApp(const MyApp());
|
void main() => runApp(const MyApp());
|
||||||
|
|
||||||
// [Other code here]
|
// [Other code here]
|
||||||
|
|
||||||
class _MyHomePageState extends State<MyHomePage> {
|
class _MyHomePageState extends State<MyHomePage> {
|
||||||
// Create an instance of the updater class
|
|
||||||
final updater = ShorebirdUpdater();
|
final updater = ShorebirdUpdater();
|
||||||
|
Patch? _currentPatch;
|
||||||
|
bool _updateAvailable = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
// Get the current patch number and print it to the console.
|
// Read the current patch number (null if no patch is installed).
|
||||||
// It will be `null` if no patches are installed.
|
updater.readCurrentPatch().then((patch) {
|
||||||
updater.readCurrentPatch().then((currentPatch) {
|
setState(() => _currentPatch = patch);
|
||||||
print('The current patch number is: ${currentPatch?.number}');
|
});
|
||||||
|
|
||||||
|
// Check if an update is available to show in the UI.
|
||||||
|
updater.checkForUpdate().then((status) {
|
||||||
|
setState(() => _updateAvailable = status == UpdateStatus.outdated);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _checkForUpdates() async {
|
// [Other code here]
|
||||||
// Check whether a new update is available.
|
|
||||||
final status = await updater.checkForUpdate();
|
|
||||||
|
|
||||||
if (status == UpdateStatus.outdated) {
|
|
||||||
try {
|
|
||||||
// Perform the update
|
|
||||||
await updater.update();
|
|
||||||
} on UpdateException catch (error) {
|
|
||||||
// Handle any errors that occur while updating.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
// [Other code here]
|
|
||||||
ElevatedButton(
|
|
||||||
child: Text('Check for update'),
|
|
||||||
onPressed: _checkForUpdates,
|
|
||||||
)
|
|
||||||
// [Other code here]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -111,23 +96,11 @@ shorebird patch android --track beta
|
|||||||
(We're just using Android for this example. Tracks are supported on all
|
(We're just using Android for this example. Tracks are supported on all
|
||||||
platforms).
|
platforms).
|
||||||
|
|
||||||
To check for updates on a given track, simply pass an `UpdateTrack` to
|
To check for updates on a given track, pass an `UpdateTrack` to
|
||||||
`checkForUpdate` and `update`. For example, this:
|
`checkForUpdate` (and `update` if you use it):
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
final status = await updater.checkForUpdate();
|
updater.checkForUpdate(track: UpdateTrack.beta);
|
||||||
if (status == UpdateStatus.outdated) {
|
|
||||||
await updater.update();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Becomes this:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
final status = await updater.checkForUpdate(track: UpdateTrack.beta);
|
|
||||||
if (status == UpdateStatus.outdated) {
|
|
||||||
await updater.update(track: UpdateTrack.beta);
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also use custom track names. When creating a patch, specify a track name
|
You can also use custom track names. When creating a patch, specify a track name
|
||||||
@@ -140,13 +113,13 @@ shorebird patch android --track my-custom-track
|
|||||||
And:
|
And:
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
const track = UpdateTrack('my-custom-track');
|
updater.checkForUpdate(track: UpdateTrack('my-custom-track'));
|
||||||
final status = await updater.checkForUpdate(track: track);
|
|
||||||
if (status == UpdateStatus.outdated) {
|
|
||||||
await updater.update(track: track);
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Note:** Updating to a specific track does not uninstall patches from other
|
||||||
|
tracks. See [#3484](https://github.com/shorebirdtech/shorebird/issues/3484)
|
||||||
|
for details.
|
||||||
|
|
||||||
## Join us on Discord!
|
## Join us on Discord!
|
||||||
|
|
||||||
We have an active [Discord server](https://discord.gg/shorebird) where you can
|
We have an active [Discord server](https://discord.gg/shorebird) where you can
|
||||||
|
|||||||
@@ -135,6 +135,21 @@ abstract class ShorebirdUpdater {
|
|||||||
/// If this detects that the current patch has been rolled back, the current
|
/// If this detects that the current patch has been rolled back, the current
|
||||||
/// patch will be uninstalled.
|
/// patch will be uninstalled.
|
||||||
/// A separate call to `update()` is required to install new patches.
|
/// A separate call to `update()` is required to install new patches.
|
||||||
|
///
|
||||||
|
/// **Warning:** This method makes a network call that may take a long time
|
||||||
|
/// to complete. If your app gates startup on the result (e.g. waiting in
|
||||||
|
/// `initState` before showing content), the app may appear stuck on the
|
||||||
|
/// splash screen. Use `.then()` to avoid blocking app progression:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// // Do this:
|
||||||
|
/// updater.checkForUpdate().then((status) {
|
||||||
|
/// // handle status
|
||||||
|
/// });
|
||||||
|
///
|
||||||
|
/// // Avoid this in startup code — app won't progress until it completes:
|
||||||
|
/// final status = await updater.checkForUpdate();
|
||||||
|
/// ```
|
||||||
Future<UpdateStatus> checkForUpdate({UpdateTrack? track});
|
Future<UpdateStatus> checkForUpdate({UpdateTrack? track});
|
||||||
|
|
||||||
/// Updates the app to the latest patch available on the specified track, or
|
/// Updates the app to the latest patch available on the specified track, or
|
||||||
@@ -149,6 +164,25 @@ abstract class ShorebirdUpdater {
|
|||||||
/// Note: The app must be restarted for the update to take effect.
|
/// Note: The app must be restarted for the update to take effect.
|
||||||
/// Note: This method does nothing if the updater is not available.
|
/// Note: This method does nothing if the updater is not available.
|
||||||
///
|
///
|
||||||
|
/// **Warning:** This method makes a network call to download the update,
|
||||||
|
/// which may take a long time to complete. If your app gates startup on
|
||||||
|
/// the result (e.g. waiting in `initState` before showing content), the app
|
||||||
|
/// may appear stuck on the splash screen. Use `.then()` to avoid blocking
|
||||||
|
/// app progression:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// // Do this:
|
||||||
|
/// updater.checkForUpdate().then((status) {
|
||||||
|
/// if (status == UpdateStatus.outdated) {
|
||||||
|
/// updater.update();
|
||||||
|
/// }
|
||||||
|
/// });
|
||||||
|
///
|
||||||
|
/// // Avoid this in startup code — app won't progress until it completes:
|
||||||
|
/// final status = await updater.checkForUpdate();
|
||||||
|
/// await updater.update();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
/// * [isAvailable], which indicates whether the updater is available.
|
/// * [isAvailable], which indicates whether the updater is available.
|
||||||
/// * [checkForUpdate], which should be called to check if an update is
|
/// * [checkForUpdate], which should be called to check if an update is
|
||||||
|
|||||||
Reference in New Issue
Block a user