Error: The getter 'length' was called on null - flutter

Error says:
NoSuchMethodError: The getter 'length' was called on null
It is a basic flutter music player App.
main.dart
import 'package:flute_music_player/flute_music_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Song> _songs;
#override
void initState() {
// TODO: implement initState
super.initState();
initPlayer();
}
void initPlayer() async{
var songs = await MusicFinder.allSongs();
songs=new List.from(songs);
setState(() {
_songs = songs;
});
}
#override
Widget build(BuildContext context) {
Widget home(){
new Scaffold(
appBar: new AppBar(title: new Text("Music App"),
),
body: new ListView.builder(
itemCount: _songs.length,
itemBuilder: (context,int index){
return new ListTile(
leading: new CircleAvatar(
child: new Text(_songs[index].title[0]),
),
title: new Text(_songs[index].title),
);
}),
);
}
return new MaterialApp(
home: home(),
);
}
}
pubspec.yaml
name: music_player
description: A new Flutter application.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
flute_music_player:
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
It should show the list of musics as result but gives an unexpected error.I am running on android.Plz help me out.
It should show the list of musics as result but gives an unexpected error.I am running on android.Plz help me out.

Change itemCount: _songs.length to itemCount: _songs?.length ?? 0 - it helps to avoid exception

Since you're performing an async operation, that would take certain amount of time so when your app first builds, the songs array is null. Try to start with an empty array instead of a null array: List<Song> _songs = []; then, when the async operation is completed the setState will make the widget to rebuild and show the array with data.

Related

Wrap.builder like in ListView.builder

I want to use Wrap on large amount of objects.
I tried to just map all object to children but it cause serious performance issue.
I want some alternative way to build only currently displayed widgets but with style of Wrap.
Some code:
Wrap(
children: list.map(createCardFromData), // List contains 20'000 items
);
This is really good example flutter is missing in my opinion.
This is also something which is being discussed on Flutter's repo
https://github.com/flutter/flutter/issues/97544
Unfortunately, it will take some time for it to be in stable release. For the time being, I would suggest to paginate the data into chunks of maybe 100 items. There are other ways as well which might involve a lot of calculations. Meanwhile, I (or maybe some other person) could try to come up with a efficient solution and maybe contribute to the Flutter.
After some fiddling, I could build sample app per your requirement.
pubspec.yaml
name: scrollable_wrap
description: A new Flutter project.
publish_to: "none"
version: 1.0.0+1
environment:
sdk: ">=2.18.4 <3.0.0"
dependencies:
cupertino_icons: ^1.0.2
flutter:
sdk: flutter
flutter_svg: ^1.1.6
random_avatar: ^0.0.7
random_words: ^1.0.2
dynamic_layouts:
git:
url: git#github.com:flutter/packages.git
path: packages/dynamic_layouts
dev_dependencies:
flutter_lints: ^2.0.0
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
main.dart
import 'package:dynamic_layouts/dynamic_layouts.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:random_avatar/random_avatar.dart';
import 'package:random_words/random_words.dart';
class Item {
final String label;
final String avatar;
Item(this.label) : avatar = randomAvatarString(label);
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Scrollable Wrap',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Item> data = [];
int n = 100000;
void init() async {
data = generateNoun().take(n).map((e) => Item(e.asString)).toList();
setState(() {});
}
#override
void initState() {
super.initState();
init();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Scrollable Wrap'),
),
body: CustomScrollView(slivers: [
DynamicSliverGrid(
gridDelegate: const SliverGridDelegateWithWrapping(
mainAxisSpacing: 0,
crossAxisSpacing: 0,
childCrossAxisExtent: double.infinity,
childMainAxisExtent: double.infinity,
),
delegate: SliverChildBuilderDelegate(
(context, index) {
if (kDebugMode) {
print('build called for $index');
}
final item = data[index];
return Chip(
key: ValueKey(item),
label: Text('$index ${item.label}'),
avatar: SvgPicture.string(item.avatar),
);
},
childCount: data.length,
),
),
]),
);
}
}
Output
Please use flutter run --no-sound-null-safety as one of the library is not null-safe. Also, you might find lag as lots of svgs are being processed on scroll. It might not happen in production.
Do you need this many items loaded at once? You're probably using a scroll view anyway, so the user only initially sees a small batch of items rather than all of them, until they actually scroll for more. What you're looking for is lazy loading, maybe combined with a technique like infinite scroll.
Try a ListView (specifically, ListView.builder) where each item contains a Wrap widget (say, each 10 items - but you may want to experiment with this number until you see a balance between performance and visual appeal).
Or, alternatively, you may code your own Wrap that does loading lazily and reuses its views, so that it only loads and displays a couple of its children as needed, not thousands at once.
If your items are fixed width you could try something like this:
import 'dart:math';
import 'package:flutter/cupertino.dart';
typedef ValueWidgetBuilder<T> = Widget Function(T value);
class WrapBuilder extends StatelessWidget {
final double itemWidth;
final List items;
final ValueWidgetBuilder itemBuilder;
const WrapBuilder(
{Key? key,
required this.itemWidth,
required this.items,
required this.itemBuilder})
: super(key: key);
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
var cardsPerRow = max(1, constraints.maxWidth ~/ itemWidth);
return ListView.builder(
shrinkWrap: true,
controller: ScrollController(),
itemCount: (items.length / cardsPerRow).ceil(),
itemBuilder: (BuildContext context, int index) {
var rowItems = items.sublist(cardsPerRow * index,
min(cardsPerRow * (index + 1), items.length));
return Row(children: [
for (final item in rowItems)
SizedBox(
width: itemWidth,
child: itemBuilder(item))
]);
},
);
});
}
}
And then use like
WrapBuilder(
itemWidth: 100, //example
items: list,
itemBuilder: createCardFromData);

Flutter 1.22.6 - url_launcher - Sending HTML email

I have two problems with the url_launcher: ^5.7.10
First Problem:
When I try to send an email with html tag, on a real device, if I use Gmail application the body of my email is not well formated. I see the HTML tags. I tried with or without HTML5 doctype
Second Problem:
When I try to send an email with an Href tag the email body is cut at the equal sign.
My code is
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'URL Launcher',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'URL Launcher'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<void> _sendMailHtml(String url) async {
if (await canLaunch(url)) {
await launch(
url
);
} else {
throw 'Could not launch $url';
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () => setState(() {
_launched = _sendMailHtml('mailto:smith#example.org?subject=News&body=<h1>Header 1</h1><p>Paragraph</p>');
}),
child: const Text('Send Mail HTML'),
),
RaisedButton(
onPressed: () => setState(() {
_launched = _sendMailHtml('mailto:smith#example.org?subject=News&body=<h1>Header 1</h1><p>Paragraph</p>Link<p>End of mail</p>');
}),
child: const Text('Send Mail HTML With HREF'),
),
],
),
],
),
);
}
}
My pubspec.yaml is
name: flutter_app
description: A new Flutter application.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
url_launcher: ^5.7.10
cupertino_icons: ^1.0.0
dev_dependencies:
flutter_test:
sdk: flutter
# The following section is specific to Flutter.
flutter:
uses-material-design: true
I did not try with flutter 2 because my app is in production and I have some dependencies errors.
For the first problem if I try with another email app, I can see the good formatting.
On Android 10...
screenshots :
first problem on Gmail app
on other email app
Second problem with Gmail and anchor tag
The mailto body parameter only supports plaintext messages. See this question.
If you want you can check out the mailer package which has an interface for sending HTML emails, as shown in the linked page.

How to save File Selected from filepicker_windows in Disk (Flutter Desktop)

Please I need assistance.
I have written below code to saved file selected from filepicker_windows to C: drive.
filepicker_windows worked well and it get my C: drive successfully But not saving the file.
It gives me ERROR "Exception has occurred.
NoSuchMethodError (NoSuchMethodError: Class 'String' has no instance getter 'bodyBytes'.
Receiver: "C:\Users\norak\OneDrive\Pictures\afdb\Capture.PNG"
Tried calling: bodyBytes)"
Below is my code, please help correct it.
pubspec.yaml File
name: file_manager
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
filepicker_windows: ^2.0.0
path_provider: ^2.0.1
provider: ^5.0.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
MAIN PAGE
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:filepicker_windows/filepicker_windows.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<String> getPicturesPath() async {
Directory docDir = await getApplicationDocumentsDirectory();
var pathList = docDir.path.split('\\');
pathList[pathList.length - 1] = 'Pictures';
var picturePath = pathList.join('\\');
print(picturePath);
return picturePath;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("File Management"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'Testing',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final file = OpenFilePicker()
..filterSpecification = {'All Files': '*.*'}
..defaultFilterIndex = 0
..defaultExtension = 'doc'
..title = 'Select a document';
final result = file.getFile();
if (result != null) {
print(result.path);
saveImage(result.path, 'ik.jpg');
print("Saved");
}
},
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
void saveImage(imageData, String imageName) async {
var picturesPath = await getPicturesPath();
var thetaImage = await File(join(picturesPath, 'theta_images', imageName))
.create(recursive: true);
await thetaImage.writeAsBytes(imageData.bodyBytes);
}
}
await thetaImage.writeAsBytes(imageData.bodyBytes); //This is the line that is given error
Please advice
Why don't you debug your code? It's a string. That's why you got the error.
Change the code to:
await thetaImage.writeAsBytes(File(imageData).readAsBytesSync());
> final directory = await getApplicationDocumentsDirectory();
final path = directory.path;
final file = File(path);

Having problem w/ flutter mobx RadioListTile

I'm having problems with mobx and radiobox: screen don't update when selected. I think it's a silly mistake, here are my main.dart, teste_store.dart and pubspec.yaml. The partial file .g was generated with build_runner and mobx_codegen.
A message appears when I run it: "No observables detected in the build method of Observer". I thought testeStore.selected was an observable and when changes triggers Observer to rebuild.
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:teste_flutter/teste_store.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TesteStore testeStore = TesteStore();
#override
Widget build(BuildContext context) {
List<String> options = ["Option 1", "Option 2", "Option 3"];
return Scaffold(
appBar: AppBar(
title: Text("Test Flutter"),
),
body: Center(
child: Observer(
builder: (_){
return ListView.builder(
itemCount: options.length,
itemBuilder: (context, index) {
return RadioListTile<int>(
title: Text(options[index]),
value: index,
groupValue: testeStore.selected,
onChanged: testeStore.changeSelected,
);
},
);
}
)
),
);
}
}
teste_store.dart
import 'package:mobx/mobx.dart';
part 'teste_store.g.dart';
class TesteStore = _TesteStore with _$TesteStore;
abstract class _TesteStore with Store {
#observable
int selected = 0;
#action
void changeSelected(int newSelected) {
selected = newSelected;
}
}
pubspec.yaml
name: teste_flutter
description: A new Flutter application.
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.0
mobx: ^1.2.1+2
flutter_mobx: ^1.1.0+2
provider: ^4.3.2+2
dev_dependencies:
flutter_test:
sdk: flutter
build_resolvers: ^1.3.10
mobx_codegen: ^1.1.0+1
build_runner: ^1.10.2
flutter:
uses-material-design: true
Edit 1 and 2:
I put the solution I found here and I shouldn't. Writing down in an answer box.
Talking to #BambinoUA, we found out a solution, just to add insight why his solution works.
I did put List view inside a Column with a sibling text widget with testeStore.selected like a text, now everything updates.
child: Observer(
builder: (_){
return Column(
children: [
Text(testeStore.selected.toString()),
ListView.builder(
itemCount: options.length,
itemBuilder: (context, index) {
return RadioListTile<int>(
title: Text(options[index]),
value: index,
groupValue: testeStore.selected,
onChanged: testeStore.changeSelected,
);
},
),
],
);
}
)
Back to original code I tried to only use print(testeStore.selected); before return inside builder of the Observer and it worked:
child: Observer(
builder: (_){
print(testeStore.selected);
return ListView.builder(
When I put inside the itemBuilder from RadioListTile don't work.
child: Observer(
builder: (_){
return ListView.builder(
itemCount: options.length,
itemBuilder: (context, index) {
print(testeStore.selected);
return RadioListTile<int>(
I assume Observer don't look changes inside other widgets builder.
I see that your TesteStore class is derived from private _TesteStore class. Maybe this is the case? And the error message looks reasonable. Try to make class with #observable public and re-build part file.
Update
Try to do intermediate assignments in Observer builder
final selected = testeStore.selected;
and then use new local variable selected inside inner builder.
Try to use ListView instead ListView.builder.
Try wrap with Observer not the List but RadioListTile.

How to get paragraphs in Flutter textfield or textformfield?

I am building a form that includes fields for notes. I want the user to be able to hit enter/return and start a new paragraph.
I am able to create a field that will accept and display large amounts of text. But I specifically want the user to be able to create paragraphs, otherwise their notes are just one long string with no breaks making it hard to read and edit.
I filed an issue here, but was told that I just need to do something like this.
This does not do want I want. I am trying to do something like this.
It looks like this should be possible (https://github.com/flutter/flutter/issues/43935). I don't know what I'm missing.
I am building for web, not iOS or Android.
main.dart:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) =>Scaffold(
body: Center(
child: Center(
child:TextFormField(
textInputAction: TextInputAction.newline,
keyboardType: TextInputType.multiline,
maxLines: 10,
),
),
),
);
}
pubspec.yaml:
name: textformfield_demo
description: A new Flutter project.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
There is a property of flutter to set max and min line. You can set maxLine:(int) Or maxLine: null, here maxLine:(int) restrict user to (int) number of line and maxLine: null will provide new line text without limit.
As-
class MultiLineEt extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _MyHomePageState();
}
}
class _MyHomePageState extends State<MultiLineEt> {
#override
Widget build(BuildContext context) =>Scaffold(
body: ListView(children: <Widget>[
new TextField(
keyboardType: TextInputType.multiline,
maxLines: null,
),
],
) );
}
Using ListView to prevent from pixels error