Flutter URL Scheme管理插件schemake的使用

发布于 1周前 作者 yuanlaile 来自 Flutter

Flutter URL Scheme管理插件schemake的使用

Schemake 是一个用于从声明性规范中描述模式的包。这些规范可以用于验证数据、生成代码或其他模式,如JSON Schema等。

Schemake的基本用法

示例1:定义和验证简单对象

import 'package:schemake/schemake.dart';
import 'dart:convert';

const person = Objects('Person', {
  'name': Property(Strings()),
  'age': Property(Nullable(Ints())),
});

void main() {
  // 验证并转换JSON字符串到Map
  final joe = person.convert(jsonDecode('{"name": "Joe"}'));
  print(joe['name']); // 输出: Joe
  print(joe['age']); // 输出: null

  // 尝试转换不合法的数据将抛出异常
  try {
    person.convert(jsonDecode('{"name": "Joe", "age": "foo"}'));
  } catch (e) {
    print(e);
  }
}

支持的数据类型

Schemake 类型 Dart 类型
Ints int
Floats double
Bools bool
Strings String
Arrays(T) List<S>
ObjectsBase<C> C
Objects Map<String, Object?>
Maps(T) Map<String, S>
Nullable(T) S?
Validatable(T) S

定义复杂的对象

class MyType {
  final String example;

  const MyType({required this.example});
}

const myTypes = Objects('MyTypes', {
  'example': Property(Strings()),
});

class MyTypes extends ObjectsBase<MyType> {
  const MyTypes() : super('MyType');

  @override
  MyType convert(Object? input) {
    final map = input as Map<String, Object?>;
    checkRequiredProperties(map.keys);
    return MyType(
      example: convertProperty(const Strings(), 'example', map),
    );
  }

  @override
  Converter<Object?, Object?>? getPropertyConverter(String property) =>
      switch (property) {
        'example' => const Strings(),
        _ => null,
      };

  @override
  Iterable<String> getRequiredProperties() => const {'example'};
}

使用Dart代码生成器

import 'package:schemake/dart_gen.dart' as dg;
import 'package:schemake/schemake.dart';

const person = Objects('Person', {
  'name': Property(Strings()),
  'age': Property(Nullable(Ints())),
});

void main() {
  print(dg.generateDartClasses([person],
      options: const dg.DartGeneratorOptions(methodGenerators: [
        ...dg.DartGeneratorOptions.defaultMethodGenerators,
        dg.DartToJsonMethodGenerator(),
        dg.DartFromJsonMethodGenerator(),
      ])));
}

生成的Dart类示例:

class Person {
  final String name;
  final int? age;

  const Person({
    required this.name,
    this.age,
  });

  static Person fromJson(Object? value) => ...;

  Map<String, Object?> toJson() => ...;

  @override
  String toString() => 'Person{name: "$name", age: $age}';

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Person &&
          runtimeType == other.runtimeType &&
          name == other.name &&
          age == other.age;

  @override
  int get hashCode => name.hashCode ^ age.hashCode;
}

JSON 和 YAML 处理

import 'package:yaml/yaml.dart';

void main() {
  Person aPerson = Person.fromJson(loadYaml('name: Mary'));

  // 打印: Person{name: "Mary", age: null}
  print(aPerson);
}

完整示例 Demo

以下是一个完整的示例,展示如何使用Schemake定义一个复杂对象,并生成对应的Dart类。

import 'dart:io';
import 'package:schemake/dart_gen.dart';
import 'package:schemake/schemake.dart';
import 'package:yaml/yaml.dart';

const personSchema = Objects('Person', {
  'name': Property(Strings()),
  'age': Property(Nullable(Ints())),
  'job': Property(Nullable(Strings())),
  'friends': Property(Arrays<String, Strings>(Strings()))
});

void main() {
  final yaml = loadYaml('''
  name: Joe Doe
  age: 42
  friends: [ "Mary", "Fred" ]
  ''');

  Map<String, Object?> joe = personSchema.convert(yaml);
  print('// Full name: ${joe['name']}');
  print('// Age:       ${joe['age']}');
  print('// Job:       ${joe['job'] ?? "unknown"}');
  final friends = joe['friends'] as List<String>;
  print('// Friends:   ${friends.join(', ')}');

  try {
    personSchema.convert(loadYaml('name: Fred'));
  } on MissingPropertyException catch (e) {
    stderr.writeln('Missing properties: ${e.missingProperties}');
  }

  print(generateDartClasses([personSchema],
      options: const DartGeneratorOptions(methodGenerators: [
        ...DartGeneratorOptions.defaultMethodGenerators,
        DartToJsonMethodGenerator(),
        DartFromJsonMethodGenerator(),
      ])));

  print(r'''
void main() {
  final person = Person(name: 'Joe Doe', age: 42, job: "Developer", friends: ['Mary']);
  print(jsonEncode(person));
  final otherPerson = Person.fromJson(
    '{"name": "Mary Jane", "friends": ["Joe"]}');
  print(otherPerson.toJson());
}
  ''');
}

更多关于Flutter URL Scheme管理插件schemake的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter URL Scheme管理插件schemake的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter应用中管理URL Scheme可以使用schemake插件来实现。schemake是一个帮助定义和管理URL Scheme的插件,尽管需要注意的是,schemake本身并不是一个广泛知名的Flutter插件(可能是自定义的或特定项目中的插件),但我们可以基于Flutter中常见的URL Scheme管理方式来提供一个类似的实现案例。

Flutter中管理URL Scheme通常涉及以下步骤:

  1. 在iOS项目中配置URL Scheme

    • 编辑ios/Runner/Info.plist文件,添加自定义的URL Scheme。
  2. 在Android项目中配置URL Scheme

    • 编辑android/app/src/main/AndroidManifest.xml文件,添加intent-filter来声明URL Scheme。
  3. 在Flutter代码中处理URL

    • 使用dart:ui中的window.defaultRouteName或者url_launcher插件来接收和处理URL。

下面是一个示例,展示如何在Flutter应用中配置和处理URL Scheme:

1. 配置iOS URL Scheme

编辑ios/Runner/Info.plist文件,添加如下内容:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>mycustomscheme</string>
        </array>
    </dict>
</array>

2. 配置Android URL Scheme

编辑android/app/src/main/AndroidManifest.xml文件,在<activity>标签内添加intent-filter:

<activity
    android:name=".MainActivity"
    android:label="flutter_app"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="mycustomscheme" android:host="*" />
    </intent-filter>
</activity>

3. 在Flutter代码中处理URL

使用window.defaultRouteName来获取启动时的URL Scheme:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    String initialRoute = window.defaultRouteName ?? '/';
    
    return MaterialApp(
      title: 'Flutter URL Scheme Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: initialRoute,
      routes: {
        '/': (context) => HomeScreen(),
        '/deep-link': (context) => DeepLinkScreen(url: initialRoute),
        // Add more routes as needed
      },
      onGenerateRoute: (settings) {
        // Custom route handling if needed
        return MaterialPageRoute(builder: (context) => HomeScreen());
      },
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: Text('This is the Home Screen'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // Simulate opening the app with a deep link
          // Note: This is just for demonstration. In a real app, this would be handled by the OS.
          Navigator.pushNamed(context, '/deep-link?path=some/deep/link');
        },
        tooltip: 'Open Deep Link',
        child: Icon(Icons.open_in_new),
      ),
    );
  }
}

class DeepLinkScreen extends StatelessWidget {
  final String url;

  DeepLinkScreen({required this.url});

  @override
  Widget build(BuildContext context) {
    Uri uri = Uri.parse(url);
    String path = uri.pathSegments.isNotEmpty ? uri.pathSegments.join('/') : 'No Path';
    Map<String, String> queryParams = uri.queryParameters;

    return Scaffold(
      appBar: AppBar(
        title: Text('Deep Link Screen'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('URL: $url'),
            Text('Path: $path'),
            Text('Query Parameters: ${queryParams.toString()}'),
          ],
        ),
      ),
    );
  }
}

在上面的代码中,我们定义了两个路由://deep-link。当应用通过URL Scheme(如mycustomscheme://some/deep/link)启动时,window.defaultRouteName将包含这个URL,然后我们可以根据URL解析出路径和查询参数,并在相应的屏幕上显示这些信息。

请注意,上述代码是一个基本的示例,实际项目中可能需要根据具体需求进行更多的配置和处理。

回到顶部