import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../repository/repository.dart';
import 'about.dart';
import 'common/form_row.dart';
import 'ndef_format.dart';
import 'ndef_write.dart';
import 'ndef_write_lock.dart';
import 'tag_read.dart';
class App extends StatelessWidget {
static Future<Widget> withDependency() async {
final repo = await Repository.createInstance();
return MultiProvider(
providers: [
Provider<Repository>.value(
value: repo,
),
],
child: App(),
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: _Home(context: context),
theme: _themeData(Brightness.light),
darkTheme: _themeData(Brightness.dark),
);
}
}
class _Home extends StatelessWidget {
final BuildContext context;
const _Home({super.key, required this.context});
@override
Widget build(BuildContext context) {
context = this.context;
return Scaffold(
appBar: AppBar(
title: Text('NFC Manager'),
),
body: ListView(
padding: EdgeInsets.all(2),
children: [
FormSection(children: [
FormRow(
title: Text('Tag - Read'),
trailing: Icon(Icons.chevron_right),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TagReadPage.withDependency(),
)),
),
FormRow(
title: Text('Ndef - Write'),
trailing: Icon(Icons.chevron_right),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NdefWritePage.withDependency(),
)),
),
FormRow(
title: Text('Ndef - Write Lock'),
trailing: Icon(Icons.chevron_right),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NdefWriteLockPage.withDependency(),
)),
),
if (Platform.isAndroid)
FormRow(
title: Text('Ndef - Format'),
trailing: Icon(Icons.chevron_right),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NdefFormatPage.withDependency(),
)),
),
]),
FormSection(children: [
FormRow(
title: Text('About'),
trailing: Icon(Icons.chevron_right),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AboutPage(),
)),
),
]),
],
),
);
}
}
ThemeData _themeData(Brightness brightness) {
return ThemeData(
brightness: brightness,
// Matches app icon color.
primarySwatch: MaterialColor(0xFF4D8CFE, <int, Color>{
50: Color(0xFFEAF1FF),
100: Color(0xFFCADDFF),
200: Color(0xFFA6C6FF),
300: Color(0xFF82AFFE),
400: Color(0xFF689DFE),
500: Color(0xFF4D8CFE),
600: Color(0xFF4684FE),
700: Color(0xFF3D79FE),
800: Color(0xFF346FFE),
900: Color(0xFF255CFD),
}),
appBarTheme: AppBarTheme(
brightness: Brightness.dark,
),
inputDecorationTheme: InputDecorationTheme(
isDense: true,
border: OutlineInputBorder(),
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 12),
errorStyle: TextStyle(height: 0.75),
helperStyle: TextStyle(height: 0.75),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
minimumSize: Size.fromHeight(40),
)),
scaffoldBackgroundColor:
brightness == Brightness.dark ? Colors.black : null,
cardColor:
brightness == Brightness.dark ? Color.fromARGB(255, 28, 28, 30) : null,
dialogTheme: DialogTheme(
backgroundColor: brightness == Brightness.dark
? Color.fromARGB(255, 28, 28, 30)
: null,
),
highlightColor:
brightness == Brightness.dark ? Color.fromARGB(255, 44, 44, 46) : null,
splashFactory: NoSplash.splashFactory,
);
}
导航到
NdefWritePage.withDependency()
时出现错误
The following ProviderNotFoundException was thrown building NdefWritePage(dirty):
Error: Could not find the correct Provider<Repository> above this _InheritedProviderScope<NdefWriteModel?> Widget
This happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:
- You added a new provider in your `main.dart` and performed a hot-reload.
To fix, perform a hot-restart.
- The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
- You used a `BuildContext` that is an ancestor of the provider you are trying to read.
Make sure that _InheritedProviderScope<NdefWriteModel?> is under your MultiProvider/Provider<Repository>.
This usually happens when you are creating a provider and trying to read it immediately.
文件中的
stream: Provider.of<NdefWriteModel>(context, listen: false).subscribe(),
行
NdefWriteModel(this._repo);
final Repository _repo;
Stream<Iterable<WriteRecord>> subscribe() {
return _repo.subscribeWriteRecordList();
}
Future<void> delete(WriteRecord record) {
return _repo.deleteWriteRecord(record);
}
Future<String?> handleTag(
NfcTag tag, Iterable<WriteRecord> recordList) async {
final tech = Ndef.from(tag);
if (tech == null) throw ('Tag is not ndef.');
if (!tech.isWritable) throw ('Tag is not ndef writable.');
try {
final message = NdefMessage(recordList.map((e) => e.record).toList());
await tech.write(message);
} on PlatformException catch (e) {
throw (e.message ?? 'Some error has occurred.');
}
return '[Ndef - Write] is completed.';
}
}
class NdefWritePage extends StatelessWidget {
static Widget withDependency() => ChangeNotifierProvider<NdefWriteModel>(
create: (context) =>
NdefWriteModel(Provider.of(context, listen: false)),
child: NdefWritePage(),
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ndef - Write'),
),
body: StreamBuilder<Iterable<WriteRecord>>(
stream: Provider.of<NdefWriteModel>(context, listen: false).subscribe(),
builder: (context, ss) => ListView(
padding: EdgeInsets.all(2),
children: [
FormSection(children: [
FormRow(
title: Text('Add Record'),
trailing: Icon(Icons.chevron_right),
onTap: () async {
final result = await showDialog<String>(
context: context,
builder: (context) => SimpleDialog(
title: Text('Record Types'),
children: [
SimpleDialogOption(
child: Text('Text'),
onPressed: () => Navigator.pop(context, 'text'),
),
SimpleDialogOption(
child: Text('Uri'),
onPressed: () => Navigator.pop(context, 'uri'),
),
SimpleDialogOption(
child: Text('Mime'),
onPressed: () => Navigator.pop(context, 'mime'),
),
SimpleDialogOption(
child: Text('External'),
onPressed: () => Navigator.pop(context, 'external'),
),
],
),
);
switch (result) {
case 'text':
Navigator.push(
context,
MaterialPageRoute(
fullscreenDialog: true,
builder: (context) => EditTextPage.withDependency(),
));
break;
case 'uri':
Navigator.push(
context,
MaterialPageRoute(
fullscreenDialog: true,
builder: (context) => EditUriPage.withDependency(),
));
break;
case 'mime':
Navigator.push(
context,
MaterialPageRoute(
fullscreenDialog: true,
builder: (context) => EditMimePage.withDependency(),
));
break;
case 'external':
Navigator.push(
context,
MaterialPageRoute(
fullscreenDialog: true,
builder: (context) =>
EditExternalPage.withDependency(),
));
break;
case null:
break;
default:
throw ('unsupported: result=$result');
}
},
),
FormRow(
title: Text('Start Session',
style: TextStyle(
color: ss.data?.isNotEmpty != true
? Theme.of(context).disabledColor
: Theme.of(context).colorScheme.primary,
)),
onTap: ss.data?.isNotEmpty != true
? null
: () => startSession(
context: context,
handleTag: (tag) => Provider.of<NdefWriteModel>(
context,
listen: false)
.handleTag(tag, ss.data!),
),
),
]),
if (ss.data?.isNotEmpty == true)
FormSection(
header: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('RECORDS'),
Text(
'${ss.data!.map((e) => e.record.byteLength).reduce((a, b) => a + b)} bytes'),
],
),
children: List.generate(ss.data!.length, (i) {
final record = ss.data!.elementAt(i);
return _WriteRecordFormRow(i, record);
}),
),
],
),
),
);
}
}```
i went throught the solution proposed [use-provider-to-update-scaffold-from-a-second-screen](https://stackoverflow.com/questions/66480332/use-provider-to-update-scaffold-from-a-second-screen/66486075#66486075) but either i am not well using it or it's not more working?
[use-provider-to-update-scaffold-from-a-second-screen](https://stackoverflow.com/questions/66480332/use-provider-to-update-scaffold-from-a-second-screen/66486075#66486075)
I expected to get out of this error but unfortunately it's didn't work
我偶然发现了这个代码库的类似问题。确保在任何依赖于
ChangeNotifierProvider
的小部件之上声明 Provider
。
您使用的是
withDependency
方法,这是正确的方法,乍一看,我没有发现任何错误。但是,有时热重载不起作用,当我将导航从 NdefReadPage()
更改为 NdefWritePage.withDepenency()
时,我必须重建并重新部署应用程序,才能使其正常工作。