Until step 2.6: :)

Read steps for more details.
This commit is contained in:
Siahlooei 2024-07-14 18:57:07 +03:30
parent b90e02bcae
commit 91ffce2869
12 changed files with 307 additions and 193 deletions

68
Steps
View File

@ -15,4 +15,72 @@
<<
1.3. Add Links.txt file.
1.4. Checkout in other station ==> Must re run 1.1. steps again. (I don't Know why)
1.5. After a while, i read the document. Now updated some dependencies and starting
use riverpod again.
Now I know many things about it, but riverpod learning curve is not good.
Flutter was better but not good at result. I will stick on learning curve before
developing the app.
2. https://riverpod.dev/docs/essentials/first_request
2.1. Install freezed using this commands:
(using https://github.com/rrousselGit/freezed?tab=readme-ov-file#install)
>>
flutter pub add freezed_annotation
flutter pub add dev:build_runner
flutter pub add dev:freezed
flutter pub add json_annotation
flutter pub add dev:json_serializable
<<
install flutterX & FlutterAssetsGenerator & freezed plugins.
2.2. Add model for utc and random endpoints.
Do these steps for any JSON, request or response.
Use snippet freezedClass, then use @freezed menu, then "Json From Freezed"
then paste,then click the button --> then change class name, file name, path then save.
Now paste in this
import 'package:flutter/foundation.dart';
to generated file.
Now use @freezed menu, then "Run Build Runner".
2.3. Run command
>>
flutter pub add http
<<
2.4. New file then paste this code. For random API. (GET http://localhost:3000/p/random)
>>
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../model/my_random.dart';
// Necessary for code-generation to work
part 'provider.g.dart';
/// This will create a provider named `activityProvider`
/// which will cache the result of this function.
@riverpod
Future<MyRandom> getMyRandom(GetMyRandomRef ref) async {
// Using package:http, we fetch a random activity from the Bored API.
final response = await http.get(Uri.https('localhost:3000', '/p/random'));
// Using dart:convert, we then decode the JSON payload into a Map data structure.
final json = jsonDecode(response.body) as Map<String, dynamic>;
// Finally, we convert the Map into an Activity instance.
return MyRandom.fromJson(json);
}
<<
Check the pattern should be with this format:
@riverpod
Result myFunction(MyFunctionRef ref) {
<your logic here>
}
myFunction and MyFunctionRef
xabcd and XabcdRef
2.5. Create a widget with data.
it is simple using these line of code
final AsyncValue<MyRandom> myRandom = ref.watch(getMyRandomProvider);
that serves data as a aysncvalue.
there is a sample in widgets/simples folder.
Note: Continue from "Going further" in "https://riverpod.dev/docs/essentials/first_request"

View File

@ -9,6 +9,10 @@
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
analyzer:
errors:
invalid_annotation_target: ignore
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`

View File

@ -0,0 +1,5 @@
///This file is automatically generated. DO NOT EDIT, all your changes would be lost.
class Assets {
Assets._();
}

View File

@ -1,125 +0,0 @@
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// TRY THIS: Try running your application with "flutter run". You'll see
// the application has a purple toolbar. Then, without quitting the app,
// try changing the seedColor in the colorScheme below to Colors.green
// and then invoke "hot reload" (save your changes or press the "hot
// reload" button in a Flutter-supported IDE, or press "r" if you used
// the command line to start the app).
//
// Notice that the counter didn't reset back to zero; the application
// state is not lost during the reload. To reset the state, use hot
// restart instead.
//
// This works for code too, not just values: Most code changes can be
// tested with just a hot reload.
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// TRY THIS: Try changing the color here to a specific color (to
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
// change color while the other colors stay the same.
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
//
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
// action in the IDE, or press "p" in the console), to see the
// wireframe for each widget.
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

49
lib/mains/gt.dart Normal file
View File

@ -0,0 +1,49 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../widgets/simples/random.dart';
part 'gt.g.dart';
// We create a "provider", which will store a value (here "Hello world").
// By using a provider, this allows us to mock/override the value exposed.
@riverpod
String helloWorld(HelloWorldRef ref) {
return 'Hello world';
}
void main() {
runApp(
// For widgets to be able to read providers, we need to wrap the entire
// application in a "ProviderScope" widget.
// This is where the state of our providers will be stored.
ProviderScope(
child: MyApp(),
),
);
}
// Extend ConsumerWidget instead of StatelessWidget, which is exposed by Riverpod
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final String value = ref.watch(helloWorldProvider);
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Example')),
body: Center(
child: Column(
children: <Widget>[
Expanded(child: Text('1')),
Expanded(child: Text(value)),
Expanded(child: RandomWidget())
],
)
),
),
);
}
}

View File

@ -0,0 +1,24 @@
// GET http://localhost:3000/p/random
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../model/my_random.dart';
// Necessary for code-generation to work
part 'getRandomData.g.dart';
/// This will create a provider named `activityProvider`
/// which will cache the result of this function.
@riverpod
Future<MyRandom> getMyRandom(GetMyRandomRef ref) async {
// Using package:http, we fetch a random activity from the Bored API.
var ur = Uri.http('192.168.160.207:3000', '/p/random');
final response = await http.get(ur);
// Using dart:convert, we then decode the JSON payload into a Map data structure.
final json = jsonDecode(response.body) as Map<String, dynamic>;
// Finally, we convert the Map into an Activity instance.
return MyRandom.fromJson(json);
}

View File

@ -0,0 +1,22 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';
part 'my_random.freezed.dart';
part 'my_random.g.dart';
@freezed
class MyRandom with _$MyRandom {
const MyRandom._();
const factory MyRandom({
@JsonKey(name: 'complexV') @Default('') String complexv,
@JsonKey(name: 'floatV') @Default(0) num floatv,
@JsonKey(name: 'intV') @Default(0) num intv,
@JsonKey(name: 'nowV') @Default(0) num nowv
}) = _MyRandom;
factory MyRandom.fromJson(Map<String,dynamic> json) => _$MyRandomFromJson(json);
}

View File

@ -0,0 +1,17 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';
part 'time.freezed.dart';
part 'time.g.dart';
@freezed
class ServerTime with _$ServerTime {
const ServerTime._();
const factory ServerTime({@JsonKey(name: 'utc') @Default('') String utc}) =
_ServerTime;
factory ServerTime.fromJson(Map<String, dynamic> json) =>
_$ServerTimeFromJson(json);
}

View File

@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_flutter_tuts/outerapi/auth/call/getRandomData.dart';
import '../../outerapi/auth/model/my_random.dart';
/// The homepage of our application
class RandomWidget extends StatelessWidget {
const RandomWidget({super.key});
@override
Widget build(BuildContext context) {
return Consumer(
builder: (context, ref, child) {
final AsyncValue<MyRandom> myRandom = ref.watch(getMyRandomProvider);
return Center(
child: switch (myRandom) {
AsyncData(:final MyRandom value ) => Text(
'myRandom: ${value}'
),
AsyncError() => const Text('Oops, something unexpected happened'),
_ => const CircularProgressIndicator(),
},
);
},
);
}
}

View File

@ -69,10 +69,10 @@ packages:
dependency: transitive
description:
name: build_daemon
sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1"
sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
url: "https://pub.dev"
source: hosted
version: "4.0.1"
version: "4.0.2"
build_resolvers:
dependency: transitive
description:
@ -85,18 +85,18 @@ packages:
dependency: "direct dev"
description:
name: build_runner
sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22"
sha256: "644dc98a0f179b872f612d3eb627924b578897c629788e858157fa5e704ca0c7"
url: "https://pub.dev"
source: hosted
version: "2.4.9"
version: "2.4.11"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799"
sha256: e3c79f69a64bdfcd8a776a3c28db4eb6e3fb5356d013ae5eb2e52007706d5dbe
url: "https://pub.dev"
source: hosted
version: "7.3.0"
version: "7.3.1"
built_collection:
dependency: transitive
description:
@ -258,10 +258,10 @@ packages:
dependency: "direct dev"
description:
name: flutter_lints
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
url: "https://pub.dev"
source: hosted
version: "2.0.3"
version: "4.0.0"
flutter_riverpod:
dependency: "direct main"
description:
@ -275,14 +275,22 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
freezed_annotation:
dependency: transitive
freezed:
dependency: "direct dev"
description:
name: freezed_annotation
sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d
name: freezed
sha256: a434911f643466d78462625df76fd9eb13e57348ff43fe1f77bbe909522c67a1
url: "https://pub.dev"
source: hosted
version: "2.4.1"
version: "2.5.2"
freezed_annotation:
dependency: "direct main"
description:
name: freezed_annotation
sha256: f9f6597ac43cc262fa7d7f2e65259a6060c23a560525d1f2631be374540f2a9b
url: "https://pub.dev"
source: hosted
version: "2.4.3"
frontend_server_client:
dependency: transitive
description:
@ -315,6 +323,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.2.0"
http:
dependency: "direct main"
description:
name: http
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
http_multi_server:
dependency: transitive
description:
@ -348,45 +364,53 @@ packages:
source: hosted
version: "0.7.1"
json_annotation:
dependency: transitive
dependency: "direct main"
description:
name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
url: "https://pub.dev"
source: hosted
version: "4.9.0"
json_serializable:
dependency: "direct dev"
description:
name: json_serializable
sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b
url: "https://pub.dev"
source: hosted
version: "6.8.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
url: "https://pub.dev"
source: hosted
version: "10.0.0"
version: "10.0.4"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "3.0.3"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
version: "4.0.0"
logging:
dependency: transitive
description:
@ -415,10 +439,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.dev"
source: hosted
version: "1.11.0"
version: "1.12.0"
mime:
dependency: transitive
description:
@ -527,10 +551,10 @@ packages:
dependency: transitive
description:
name: shelf_web_socket
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
version: "2.0.0"
sky_engine:
dependency: transitive
description: flutter
@ -544,6 +568,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.5.0"
source_helper:
dependency: transitive
description:
name: source_helper
sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd"
url: "https://pub.dev"
source: hosted
version: "1.3.4"
source_span:
dependency: transitive
description:
@ -612,10 +644,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
url: "https://pub.dev"
source: hosted
version: "0.6.1"
version: "0.7.0"
timing:
dependency: transitive
description:
@ -636,10 +668,10 @@ packages:
dependency: transitive
description:
name: uuid
sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8"
sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90"
url: "https://pub.dev"
source: hosted
version: "4.4.0"
version: "4.4.2"
vector_math:
dependency: transitive
description:
@ -652,10 +684,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.dev"
source: hosted
version: "13.0.0"
version: "14.2.1"
watcher:
dependency: transitive
description:
@ -672,14 +704,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.5.1"
web_socket:
dependency: transitive
description:
name: web_socket
sha256: "24301d8c293ce6fe327ffe6f59d8fd8834735f0ec36e4fd383ec7ff8a64aa078"
url: "https://pub.dev"
source: hosted
version: "0.1.5"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
sha256: a2d56211ee4d35d9b344d9d4ce60f362e4f5d1aafb988302906bd732bc731276
url: "https://pub.dev"
source: hosted
version: "2.4.5"
version: "3.0.0"
yaml:
dependency: transitive
description:
@ -689,5 +729,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.3.0 <4.0.0"
flutter: ">=3.0.0"
dart: ">=3.4.0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"

View File

@ -37,6 +37,9 @@ dependencies:
cupertino_icons: ^1.0.2
flutter_riverpod: ^2.5.1
riverpod_annotation: ^2.3.5
freezed_annotation: ^2.4.3
json_annotation: ^4.9.0
http: ^1.2.1
dev_dependencies:
flutter_test:
@ -47,11 +50,13 @@ dev_dependencies:
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^2.0.0
flutter_lints: ^4.0.0
riverpod_generator: ^2.4.0
build_runner: ^2.4.9
build_runner: ^2.4.11
custom_lint: ^0.6.4
riverpod_lint: ^2.3.10
freezed: ^2.5.2
json_serializable: ^6.8.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
@ -94,3 +99,6 @@ flutter:
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
assets:
- assets/image/

View File

@ -1,30 +0,0 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:riverpod_flutter_tuts/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}