Passing a URL file to firebase using flutter - flutter

I'm attempting to upload URL posterImg in the createGroup method but I get the following error "The argument type 'String' can't be assigned to the parameter type 'File"
To provide more context, I'm currently capturing the URL of images stored online using the variable posterImg, I then want to convert the path to a file without storing the image locally and then saving it to a file so it can be uploaded to firebase.
In the snippet below I have tried casting posterImg to image (which is of the type file) but it fails.
Can anyone advise how to modify my code to pass a URL stored in posterImg to the Firebase??
Please can anyone share the festive sprite and up with this problem, as I'm pulling my hair out.
class _CreateGroupScreenState extends ConsumerState<CreateGroupScreen> {
final TextEditingController groupNameController = TextEditingController();
File? image;
late String name;
late String posterImg = "";
void selectImage2() async {
image = await pickImageFromGallery(context);
setState(() {});
}
Future<void> createGroup() async {
bool groupLive;
if (await groupExist(context)) {
groupLive = true;
} else {
groupLive = false;
}
if (!groupLive && groupNameController.text
.trim()
.isNotEmpty && image != null) {
ref.read(groupControllerProvider).createGroup(
context,
name,
posterImg!,
ref.read(selectedGroupContacts),
);
ref.read(selectedGroupContacts.state).update((state) => []);
Navigator.pop(context);
}
}
#override
void dispose() {
super.dispose();
groupNameController.dispose();
}
Future<bool> groupExist(context) async {
var groupRepository = ref.read(groupRepositoryProvider);
var groupExists = await groupRepository.groupExists(widget.groupContainer.mid);
return groupExists;
}
#override
Widget build(BuildContext context) {
name = widget.groupContainer.name;
if (widget.groupContainer.img != null) {
posterImg = widget.groupContainer.img;
} else {
posterImg = '';
}
return Scaffold(
appBar: AppBar(
title: const Text('Create Group'),
),
body: Center(
child: Column(
children: [
const SizedBox(height: 10),
Stack(
children: [
image == null
? const CircleAvatar(
//backgroundImage: NetworkImage(posterImg),
backgroundImage: AssetImage('assets/nobody.png'),
//backgroundImage: AssetImage(Assets),
radius: 64,
)
: CircleAvatar(
backgroundImage: FileImage(
// posterImg,
//widget.groupContainer.img,
image!,
),
radius: 64,
),
Positioned(
bottom: -10,
left: 80,
child: IconButton(
onPressed: selectImage,
icon: const Icon(
Icons.add_a_photo,
),
),
),
],
),
Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
controller: groupNameController,
decoration: const InputDecoration(
hintText: 'Enter Group Name',
),
),
),
Container(
alignment: Alignment.topLeft,
padding: const EdgeInsets.all(8),
child: const Text(
'Select Contacts',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
),
const SelectContactsGroup(),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: createGroup,
backgroundColor: tabColor,
child: const Icon(
Icons.done,
color: Colors.white,
),
),
);
}
}

There is no way to upload a file to Cloud Storage through the Firebase SDKs from a URL. The only options are to upload from a local file, a blob, or a base64 encoded string with the binary data.
If you have only a URL of the file you want to store in Cloud Storage, you will have to load the data into your application and from there upload it to Cloud Storage.
Also see:
Upload image from URL to Firebase Storage using flutter
How to upload an image to storage firebase from an url (for Android, but the same problem)

Related

How to persist and save value from shared prefernces in Flutter?

I want to persist value after user leaves page, also I would like to persist selected values, so I found out shared prefernces and I save it locally, but when I left page and return it remains unselected.
So I decided to convert my multipleSelected list to String, because sharedprefernces can't save list of ints and sfter that save selected values in lists. So how can i solve that problem when user leaves page and selected items become unselected.
class DataBaseUser extends StatefulWidget {
const DataBaseUser({Key? key}) : super(key: key);
#override
State<DataBaseUser> createState() => _DataBaseUserState();
}
class _DataBaseUserState extends State<DataBaseUser> {
int index = 1;
/// add selected items from list
List multipleSelected = [];
/// another list to form the new list above previous one
List chosenListsAbove = [];
List basesNames = [];
SharedPreferences? sharedPreferences;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Typographys.primaryColor,
appBar: PreferredSize(
preferredSize: const Size(125, 125),
child: AppBarService(),
),
body: Column(
children: [
// chosenOne(),
Card(
color: Typographys.gradientCard2,
child: ExpansionTile(
iconColor: Colors.white,
maintainState: true,
title: Text(
'Bases',
style: TextStyle(
fontFamily: 'fonts/Montserrat',
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 35),
),
children: [
SizedBox(
height: 10,
),
getDataBaseList(),
SizedBox(
height: 22,
),
getUpdateBaseButtons(),
SizedBox(
height: 10,
),
],
),
),
],
),
);
}
Widget getDataBaseList() {
return FutureBuilder<List>(
future: BasesService().GetBases(),
builder: (context, snapshot) {
List? baseNames = snapshot.data;
print(baseNames);
return ListView.builder(
shrinkWrap: true,
itemCount: baseNames?.length ?? 0,
itemBuilder: (context, i) {
Future<void> _onCategorySelected(bool selected, id) async {
final pref = await SharedPreferences.getInstance();
if (selected == true) {
setState(() {
multipleSelected.add(id);
List<String> stringsList =
multipleSelected.map((i) => i.toString()).toList();
// store your string list in shared prefs
pref.setStringList("stringList", stringsList);
List<String> mList =
(pref.getStringList('stringList') ?? <String>[]);
print('HERE');
print(mList);
print('HERE 2');
});
} else {
setState(
() {
multipleSelected.remove(id);
},
);
}
}
return Column(
children: [
ListTile(
title: Padding(
padding: const EdgeInsets.only(left: 1.0),
child: Text(
baseNames?[i]['name'] ?? 'not loading',
style: TextStyle(
fontFamily: 'fonts/Montserrat',
fontSize: 24,
fontWeight: FontWeight.w900,
color: Colors.white),
),
),
leading: Checkbox(
activeColor: Colors.green,
checkColor: Colors.green,
side: BorderSide(width: 2, color: Colors.white),
value: multipleSelected.contains(
baseNames?[i]['id'],
),
onChanged: (bool? selected) {
_onCategorySelected(selected!, baseNames?[i]['id']);
},
)
//you can use checkboxlistTile too
),
],
);
},
);
},
);
}
Widget getUpdateBaseButtons() {
return Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FutureBuilder<bool>(
future: BasesService().SelectBaseAsync(multipleSelected.cast()),
builder: (context, snapshot) {
return ElevatedButton(
onPressed: () {
if (snapshot.data == true) {
BasesService().SelectBaseAsync(multipleSelected.cast());
print(multipleSelected.cast());
print(multipleSelected);
successSnackBar();
} else {
notSuccessSnackBar();
}
},
child: Text(
'Send bases',
style: TextStyle(
fontFamily: 'fonts/Montserrat',
fontSize: 22,
fontWeight: FontWeight.w900,
color: Colors.white,
letterSpacing: 2),
),
style: ElevatedButton.styleFrom(
minimumSize: Size(200, 40),
primary: Colors.green,
onPrimary: Colors.white,
),
);
return Container();
})
],
),
);
}
If I understand you correclty, cant you just save items in WillPopScope like
return WillPopScope(
onWillPop: () async => SaveMyPreferences,
child: const Scaffold(
body: Container(
color: Colors.red,
size: 50.0,
),
),
);
I found a solution. If your data that you want to save comes from the API and is constantly updated (as it was in my case), then you do not need to use the shared preference package. This package will not help you. In my case, in order to save the checkboxes selected by the user and after reloading the page to show him which items in the list were selected (I use checkboxes), I write to a file on the device and then read the saved data from this file. So you are going to need path_provider package and dart:io and these two functions
to write from function where you choose items
_onCategorySelected(bool selected, id) async {
final Directory directory =
await getApplicationDocumentsDirectory();
if (selected == true) {
multipleSelected.add(id);
} else {
multipleSelected.remove(id);
}
final File file = File('${directory.path}/my_file.json');
file.writeAsStringSync('{"selected": $multipleSelected}');
setState(() {});
}
to read from file:
Future<String> read() async {
String text = '';
try {
final Directory directory =
await getApplicationDocumentsDirectory();
final File file = File('${directory.path}/my_file.json');
text = await file.readAsString();
print('HELLO');
multipleSelected = json.decode(text)["selected"];
} catch (e) {
print("Couldn't read file");
}
return text;
}
and before the listview.builder comes, you need to use read() function ro read the saved values from file.
It is not the greatest solution (maybe, the worst one), but if you haven't got enough time and you don't have any state management and you just need to solve issue right now, it can be really helpfull.

UI not updating in flutter after pop

Hello there hope you all are doing well. Coming to the point I am developing a weather application in flutter its working fine but when it comes to getting weather by city its not working actually its getting all the data but not updating data in UI.
Updating UI
void updateUI(var weatherData) {
if (weatherData == null) {
city = '';
temperature = 0;
weatherMessage = 'Unable to fetch data';
}
id = weatherData['weather'][0]['id'];
weatherIcon = weatherModel.getWeatherIcon(id);
city = weatherData['name'];
double temp = weatherData['main']['temp'];
temperature = temp.toInt();
weatherMessage = weatherModel.getMessage(temperature);
description = weatherData['weather'][0]['description'];
}
Recieving city name(Here is the actual problem i guess)
FlatButton(
onPressed: () async {
dynamic typedname = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Cityscreen()));
setState(
() async {
dynamic weatherData =
await weatherModel.getCityLocation(typedname);
updateUI(weatherData);
},
);
},
Getting city location
Future<dynamic> getCityLocation(String cityname) async
{
Network_helper network_helper=Network_helper('https://api.openweathermap.org/data/2.5/weather?q=$cityname&appid=$key');
var weatherData=await network_helper.getData();
return weatherData;
}
City screen stateful widget
class _CityscreenState extends State<Cityscreen> {
late String cityName;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/back1.jpg'),
fit: BoxFit.fill,
),
),
constraints: BoxConstraints.expand(),
child: SafeArea(
child: Column(
children: [
Align(
alignment: Alignment.topLeft,
child: FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: Icon(
Icons.arrow_back_ios,
size: 50.0,
),
),
),
Container(
padding: EdgeInsets.all(20.0),
child: TextField(
style: TextStyle(
color: Colors.black,
),
decoration: kTextFieldDecoration,
onChanged: (value)
{
cityName=value;
},
),
),
FlatButton(
onPressed: (){
Navigator.pop(context,cityName);
},
child: Text(
'Get weather',
style: TextStyle(
fontSize: 30,
),
),
color: Colors.deepPurpleAccent,
),
],
),
),
),
Thanks in advance.
Use setstate in then section in navigation push code.
Navigator.push(context,MaterialPageRoute(
builder: (context) => Cityscreen())).then((value) {
setState(() async {
dynamic weatherData =
await weatherModel.getCityLocation(typedname);
updateUI(weatherData);
});
});
If answer by Laxman doesn't work well try separating setState and async code...
you can call getCityLocation() store value in a temp variable and then call setState() on assignment.
Some reference to back my answer SO post

How to share text with image on flutter excluding icons?

I am currently able to share the text on top of the image using share package but I want to share the image and text along with it without my icons of refresh and share. Couldn't find any answers for this. Have used multiple share packages but couldn't achieve the expected result.
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: <Widget>[
Container(
constraints: BoxConstraints.expand(),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage("${imgUrl}$count"),
fit: BoxFit.fill)
),
),
FutureBuilder<Advice>(
future: advice,
builder: (context, snapshot) {
if (snapshot.hasData) {
return SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 30.0),
child: FadeTransition(
opacity: _animation,
child: Text(
snapshot.data!.adviceText,
style: TextStyle(
decoration: TextDecoration.none,
fontSize: 30.0,
color: Colors.white,
fontFamily: 'quoteScript'),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(Icons.refresh, color: Colors.white),
onPressed: () async {
setState(() {
_controller.reset();
_controller.forward();
count++;
advice = fetchAdvice();
});
},
),
IconButton(
icon: Icon(Icons.share, color: Colors.white),
onPressed: () {
Share.share("Here's an advice for you: ${snapshot.data!.adviceText}");
},
),
],
),
],
),
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return Center(child: CircularProgressIndicator());
},
),
]),
);
}
This is the text and image widget. Can be shared with the dynamic text.
SHARE: The best way I think is to use screenshot package to capture the widget which contains both image and text that you need to share, then share it as a picture with share_plus package.
For instance:
// Create a controller
ScreenshotController screenshotController = ScreenshotController();
[...]
// Wrap the widget which you want to capture with `Screenshot`
Screenshot<Widget>(
controller: screenshotController,
child: Container(
child: [...]
),
),
[...]
// Create a method to take a screenshot and share it
// This method I get from my project, so you can modify it to fit your purpose
Future<void> shareScreen(String title, String name) async {
final screenShot = await screenshotController.capture();
if (screenShot != null) {
final Directory tempDir = await getTemporaryDirectory();
final File file = await File('${tempDir.path}/$name').create();
await file.writeAsBytes(screenShot);
await Share.shareFiles(<String>[file.path], subject: title, text: name);
file.delete();
}
}
Then replace the Share.share method in the below example with the shareScreen method just created above.
HIDE BUTTON: You can create a new variable like bool isSharing = false; to control the visible state of those 2 buttons. The important part is the Share.share method must be an async method to make the code works because it needs await to know when the share action is done.
For instance:
[...]
if (!isSharing) // <--- Add this line
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(Icons.refresh, color: Colors.white),
onPressed: () async {
setState(() {
_controller.reset();
_controller.forward();
count++;
advice = fetchAdvice();
});
},
),
IconButton(
icon: Icon(Icons.share, color: Colors.white),
// And modify here <---
onPressed: () async {
setState(() => isSharing = true); // Hide the buttons
await Share.share(
"Here's an advice for you: ${snapshot.data!.adviceText}");
setState(() => isSharing = false); // Show the buttons
},
),
],
),
[...]

Image is not getting loaded even after a permanent save

I am trying to create a profile page where we can select the image from the camera and that image will be set as the profile picture. I am saving the image in the directory I have access to and updating the UI after the image is captured. But when I'm restarting the app the captured image is no longer there and I'm seeing the default placeholder image after every restart. Here is the code for the image picker (using provider):
class ProfileInfoProvider with ChangeNotifier {
// this will hold the image
File? _imageFile;
// this will hold the name
late String _name;
// method to set the profile image
Future<void> setProfileImage({required ImageSource source}) async {
// instantiation image picker
ImagePicker picker = ImagePicker();
// picking the image with the source selected
XFile? pickedImage = await picker.pickImage(source: source);
// if user did pick an image
if (pickedImage != null) {
// converting the pickedImage to the pickedImageFile
File pickedImageFile = File(pickedImage.path);
// getting the image name
String imageName = pickedImage.name;
// getting the locaiton we can store the data in
String dirName = (await getApplicationDocumentsDirectory()).path;
// copying the file to the path
File copiedFile = await pickedImageFile.copy('$dirName/$imageName');
// setting the image
_imageFile = copiedFile;
// notifying the listeners
notifyListeners();
}
}
// setter to set the name
void setName(String name) {
_name = name;
// notifying listeners
notifyListeners();
}
// getter to get the image file
File? get getImageFile {
return _imageFile;
}
// getter to get the name
String get getName {
return _name;
}
}
Here is the drawer where I want the image:
class CustomDrawer extends StatelessWidget {
const CustomDrawer({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Drawer(
// this container is the background of the Drawer
child: Container(
height: double.infinity,
color: Theme.of(context).scaffoldBackgroundColor,
// this columnn will hold the First container that holds the name and the image
child: Column(
children: [
// this container holds the name and the image. Using container for a different background
Container(
width: double.infinity,
height: 200, // the dark background height
color: Theme.of(context).primaryColor,
// safe area to make sure that the content does not overlap with the notification bar
child: SafeArea(
// padding for the column
child: Padding(
padding: const EdgeInsets.all(20.0),
// this holds the actual image and name
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Consumer<ProfileInfoProvider>(
builder: (context, profileInfoPorivder, child) {
return CircleAvatar(
radius: 40,
backgroundColor: Theme.of(context).accentColor,
backgroundImage: profileInfoPorivder.getImageFile ==
null
? AssetImage('assets/images/no_profile.jpg')
: FileImage(profileInfoPorivder.getImageFile!)
as ImageProvider,
);
},
),
Text(
'Dipansh Parmar',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 18,
),
),
],
),
),
),
),
// this list view holds different options. Wrapping it inside Expanded to give it the full remaining height
Expanded(
child: ListView(
padding: const EdgeInsets.all(0),
children: [
ListTile(
onTap: () {
Navigator.pushNamed(
context,
EditProfilePage.routeName,
);
},
leading: Icon(
Icons.edit,
color: Colors.white,
size: 20,
),
title: Text(
'Edit profile',
style: TextStyle(color: Colors.white),
),
),
],
),
),
],
),
),
);
}
}
Any help will be appreciated.

Blogger API not loading on flutter

Am trying to load a blog on flutter using API. for some reasons, the file is not loading on the emulator, and the code not showing any errors or suggestions. Once i click run, after the connection, it stops abruptly... Please, if anyone can preview the code and and help me out.. The error log is saying something about immutable, which i don't really follow.. Please help.
Main.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:html/parser.dart';
import 'pages/post_view.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _isLoading = true; //For progress bar
var posts;
var imgUrl;
//initialization
void initState() {
super.initState();
_fetchData();
}
//Function to fetch data from JSON
_fetchData() async {
print("attempting");
final url =
"https://www.googleapis.com/blogger/v3/blogs/MY BLOG ID HERE/posts/?key= API KEY HERE";
final response = await http.get(url);
print(response);
if (response.statusCode == 200) {
//HTTP OK is 200
final Map items = json.decode(response.body);
var post = items['items'];
setState(() {
_isLoading = false;
this.posts = post;
});
}
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Blogger"),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.refresh),
onPressed: () {
setState(() {
_isLoading = true;
});
_fetchData();
})
],
),
body: new Center(
child: _isLoading
? new CircularProgressIndicator()
: new ListView.builder(
itemCount: this.posts != null ? this.posts.length : 0,
itemBuilder: (context, i) {
final Post = this.posts[i];
final postDesc = Post["content"];
//All the below code is to fetch the image
var document = parse(postDesc);
//Regular expression
RegExp regExp = new RegExp(
r"(https?:\/\/.*\.(?:png|jpg|gif))",
caseSensitive: false,
multiLine: false,
);
final match = regExp
.stringMatch(document.outerHtml.toString())
.toString();
//print(document.outerHtml);
//print("firstMatch : " + match);
//Converting the regex output to image (Slashing) , since the output from regex was not perfect for me
if (match.length > 5) {
if (match.contains(".jpg")) {
imgUrl = match.substring(0, match.indexOf(".jpg"));
print(imgUrl);
} else {
imgUrl =
"https://pbs.twimg.com/profile_images/916384996092448768/PF1TSFOE_400x400.jpg";
}
}
String description = document.body.text.trim();
//print(description);
return new Container(
padding:
const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 8.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
width: 500.0,
height: 180.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
image: new DecorationImage(
fit: BoxFit.fill,
//check if the image is not null (length > 5) only then check imgUrl else display default img
image: new NetworkImage(imgUrl
.toString()
.length >
10
? imgUrl.toString()
: "https://pbs.twimg.com/profile_images/916384996092448768/PF1TSFOE_400x400.jpg")),
),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 10.0),
child: new Text(
Post["title"],
maxLines: 3,
style: new TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
new Text(
description.replaceAll("\n", ", "),
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: new TextStyle(fontSize: 15.0),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0),
child: new RaisedButton(
child: new Text("READ MORE",style: new TextStyle(color: Colors.white),),
color: Colors.blue,
onPressed: () {
//We will pass description to postview through an argument
Navigator
.of(context)
.push(new MaterialPageRoute<Null>(
builder: (BuildContext context) {
return PostView(Post['title'],description,imgUrl);
},
));
},
),
),
Divider(),
],
),
);
},
)));
}
}
Post_view.dart
import 'package:flutter/material.dart';
class PostView extends StatelessWidget {
var desc, title, image;
PostView(String title, String desc, String image) {
this.desc = desc;
this.title = title;
this.image = image;
}
#override
Widget build(BuildContext context) {
if (desc.toString().contains("\n\n\n\n")) {
desc = desc.toString().replaceAll("\n\n\n\n", "\n\n");
}
if (desc.toString().contains("\n\n\n")) {
desc = desc.toString().replaceAll("\n\n\n", "\n");
}
return new Scaffold(
appBar: new AppBar(
title: new Text("Blogger"),
),
body: new Container(
child: new SingleChildScrollView(
child: new Column(
children: <Widget>[
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: new Text(
title,
style: new TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold,
),
),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: new Container(
width: 500.0,
height: 180.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
image: new DecorationImage(
fit: BoxFit.fill,
//check if the image is not null (length > 5) only then check imgUrl else display default img
image: new NetworkImage(image.toString().length > 10
? image.toString()
: "https://pbs.twimg.com/profile_images/916384996092448768/PF1TSFOE_400x400.jpg")),
),
),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: new Text(
desc,
style: new TextStyle(
fontSize: 18.0,
),
),
),
],
))),
);
}
}
The problem log reads:
main.dart: Name non-constant identifiers using lowerCamelCase.
post_view.dart: This class (or a class which this class inherits from) is marked as '#immutable', but one or more of its instance fields are not final: PostView.desc, PostView.title, PostView.image
my editor marks class post on the post_view.dart as immutable.. how do i fix that.
final url =
"https://www.googleapis.com/blogger/v3/blogs/MY_BLOG_ID_HERE/posts/?key=API_KEY_HERE";
get your blog ID and put it into the required space and also get an API key for the blog from blogger
it should look like this
final url = "https://www.googleapis.com/blogger/v3/blogs/409370562475495748/posts/?key=AIzaSyA3_4OfkfLc10vy5Q2WeUhfirGUUY4J78F8bk";
also try to make these final PostView.desc, PostView.title, PostView.image and see if it works