Skip to content

Commit

Permalink
Create a flutter example application that uses multiple client implem…
Browse files Browse the repository at this point in the history
…entations (#1040)
  • Loading branch information
brianquinlan authored Nov 7, 2023
1 parent a2f3c1d commit b2717ba
Show file tree
Hide file tree
Showing 138 changed files with 5,061 additions and 57 deletions.
262 changes: 238 additions & 24 deletions .github/workflows/dart.yml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ and the browser.
| [http_client_conformance_tests](pkgs/http_client_conformance_tests/) | A library that tests whether implementations of package:http's `Client` class behave as expected. | |
| [cronet_http](pkgs/cronet_http/) | An Android Flutter plugin that provides access to the [Cronet](https://developer.android.com/guide/topics/connectivity/cronet/reference/org/chromium/net/package-summary) HTTP client. | [![pub package](https://img.shields.io/pub/v/cronet_http.svg)](https://pub.dev/packages/cronet_http) |
| [cupertino_http](pkgs/cupertino_http/) | A macOS/iOS Flutter plugin that provides access to the [Foundation URL Loading System](https://developer.apple.com/documentation/foundation/url_loading_system). | [![pub package](https://img.shields.io/pub/v/cupertino_http.svg)](https://pub.dev/packages/cupertino_http) |
| [flutter_http_example](pkgs/flutter_http_example/) | An Flutter app that demonstrates how to configure and use `package:http`. ||
24 changes: 10 additions & 14 deletions pkgs/cronet_http/example/lib/book.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

Expand All @@ -12,20 +12,16 @@ class Book {
static List<Book> listFromJson(Map<dynamic, dynamic> json) {
final books = <Book>[];

if (json['items'] is List<dynamic>) {
final items = (json['items'] as List).cast<Map<String, Object?>>();

if (json['items'] case final List<dynamic> items) {
for (final item in items) {
if (item.containsKey('volumeInfo')) {
final volumeInfo = item['volumeInfo'] as Map;
if (volumeInfo['title'] is String &&
volumeInfo['description'] is String &&
volumeInfo['imageLinks'] is Map &&
(volumeInfo['imageLinks'] as Map)['smallThumbnail'] is String) {
books.add(Book(
volumeInfo['title'] as String,
volumeInfo['description'] as String,
(volumeInfo['imageLinks'] as Map)['smallThumbnail'] as String));
if (item case {'volumeInfo': final Map<dynamic, dynamic> volumeInfo}) {
if (volumeInfo
case {
'title': final String title,
'description': final String description,
'imageLinks': {'smallThumbnail': final String thumbnail}
}) {
books.add(Book(title, description, thumbnail));
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion pkgs/cronet_http/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class HomePage extends StatefulWidget {

class _HomePageState extends State<HomePage> {
List<Book>? _books;
String? _lastQuery;

@override
void initState() {
Expand All @@ -65,6 +66,7 @@ class _HomePageState extends State<HomePage> {
}

void _runSearch(String query) async {
_lastQuery = query;
if (query.isEmpty) {
setState(() {
_books = null;
Expand All @@ -73,6 +75,9 @@ class _HomePageState extends State<HomePage> {
}

final books = await _findMatchingBooks(query);
// Avoid the situation where a slow-running query finishes late and
// replaces newer search results.
if (query != _lastQuery) return;
setState(() {
_books = books;
});
Expand Down Expand Up @@ -127,7 +132,8 @@ class _BookListState extends State<BookList> {
leading: CachedNetworkImage(
placeholder: (context, url) =>
const CircularProgressIndicator(),
imageUrl: widget.books[index].imageUrl),
imageUrl:
widget.books[index].imageUrl.replaceFirst('http', 'https')),
title: Text(widget.books[index].title),
subtitle: Text(widget.books[index].description),
),
Expand Down
2 changes: 1 addition & 1 deletion pkgs/cronet_http/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: Demonstrates how to use the cronet_http plugin.
publish_to: 'none'

environment:
sdk: ">=2.19.0 <3.0.0"
sdk: "^3.0.0"

dependencies:
cached_network_image: ^3.2.3
Expand Down
22 changes: 9 additions & 13 deletions pkgs/cupertino_http/example/lib/book.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,16 @@ class Book {
static List<Book> listFromJson(Map<dynamic, dynamic> json) {
final books = <Book>[];

if (json['items'] is List<dynamic>) {
final items = (json['items'] as List).cast<Map<String, Object?>>();

if (json['items'] case final List<dynamic> items) {
for (final item in items) {
if (item.containsKey('volumeInfo')) {
final volumeInfo = item['volumeInfo'] as Map;
if (volumeInfo['title'] is String &&
volumeInfo['description'] is String &&
volumeInfo['imageLinks'] is Map &&
(volumeInfo['imageLinks'] as Map)['smallThumbnail'] is String) {
books.add(Book(
volumeInfo['title'] as String,
volumeInfo['description'] as String,
(volumeInfo['imageLinks'] as Map)['smallThumbnail'] as String));
if (item case {'volumeInfo': final Map<dynamic, dynamic> volumeInfo}) {
if (volumeInfo
case {
'title': final String title,
'description': final String description,
'imageLinks': {'smallThumbnail': final String thumbnail}
}) {
books.add(Book(title, description, thumbnail));
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions pkgs/cupertino_http/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class HomePage extends StatefulWidget {

class _HomePageState extends State<HomePage> {
List<Book>? _books;
String? _lastQuery;

@override
void initState() {
Expand All @@ -63,6 +64,7 @@ class _HomePageState extends State<HomePage> {
}

void _runSearch(String query) async {
_lastQuery = query;
if (query.isEmpty) {
setState(() {
_books = null;
Expand All @@ -71,6 +73,9 @@ class _HomePageState extends State<HomePage> {
}

final books = await _findMatchingBooks(query);
// Avoid the situation where a slow-running query finishes late and
// replaces newer search results.
if (query != _lastQuery) return;
setState(() {
_books = books;
});
Expand Down
44 changes: 44 additions & 0 deletions pkgs/flutter_http_example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
45 changes: 45 additions & 0 deletions pkgs/flutter_http_example/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: "367f9ea16bfae1ca451b9cc27c1366870b187ae2"
channel: "stable"

project_type: app

# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
- platform: android
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
- platform: ios
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
- platform: linux
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
- platform: macos
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
- platform: web
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
- platform: windows
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2

# User provided section

# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
43 changes: 43 additions & 0 deletions pkgs/flutter_http_example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# flutter_http_example

A Flutter sample app that illustrates how to configure and use
[`package:http`](https://pub.dev/packages/http).

## Goals for this sample

* Provide you with example code for using `package:http` in Flutter,
including:

* configuration for multiple platforms.
* using `runWithClient` and `package:provider` to pass `Client`s through
an application.
* writing tests using `MockClient`.

## The important bits

### `http_client_factory.dart`

This library used to create `package:http` `Client`s when the app is run inside
the Dart virtual machine, meaning all platforms except the web browser.

### `http_client_factory_web.dart`

This library used to create `package:http` `Client`s when the app is run inside
a web browser.

Web configuration must be done in a seperate library because Dart code cannot
import `dart:ffi` or `dart:io` when run in a web browser.

### `main.dart`

This library demonstrates how to:

* import `http_client_factory.dart` or `http_client_factory_web.dart`,
depending on whether we are targeting the web browser or not.
* share a `package:http` `Client` by using `runWithClient` and
`package:provider`.
* call `package:http` functions.

### `widget_test.dart`

This library demonstrates how to construct tests using `MockClient`.
13 changes: 13 additions & 0 deletions pkgs/flutter_http_example/android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java

# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks
67 changes: 67 additions & 0 deletions pkgs/flutter_http_example/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}

android {
namespace "com.example.flutter_http_example"
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = '1.8'
}

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.flutter_http_example"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}

buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}

flutter {
source '../..'
}

dependencies {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
Loading

0 comments on commit b2717ba

Please sign in to comment.