What is the best way to send data using an API to a springboot server using flutter? - spring

I'm working on a flutter mobile app and I'm wondering about the cleanest way to send data to a springboot server.

Here we do use flutter http package to obtain/ work with data from apis.
Here's an example
import 'package:flutter/material.dart';
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Welcome to My App",
home: AppBody(),
);
}
}
class AppBody extends StatefulWidget {
#override
_AppBodyState createState() => _AppBodyState();
}
class _AppBodyState extends State<AppBody> {
final apiURL = "localhost:8080";
final path = "/api/posts/read?search=shyam&start=1&limit=100";
late var url;
#override
void initState() {
// TODO: implement initState
super.initState();
// url = Uri.http(apiURL, path);
// url = Uri.http(apiURL+path);
url = Uri.http(amazonUri, path);
getData();
}
Future<void> getData() async {
var response = await http.get(url);
if (response.statusCode == 200) {
print("Data obtained successfully");
print(response.body);
} else {
print("Issues with APIs");
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Icon(Icons.agriculture),
title: Text("App Bar"),
),
body: Container(
child: Center(
child: Text("Hello world"),
),
),
);
}
}

**you can use dio packge for any kind of apis its easy and best and you do not need any kind maping it will be by dio package own its own **
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:rent_house/screens/Navigation/navBar.dart';
Future<String> signupApis({
name,
email,
conatact,
address,
password,
type,
context,
}) async {
// isloading:true;
var apiURL = 'https://denga.r3therapeutic.com/public/api/register';
var formData = FormData.fromMap({
'name': name,
'email': email,
'contact': conatact,
'address': address,
'password': password,
'type': type,
});
//final prefs = await SharedPreferences.getInstance();
Dio dio = Dio();
Response responce;
try {
responce = await dio.post(
apiURL,
data: formData,
);
// print("response datra " + responce.toString());
SharedPreferences pref = await SharedPreferences.getInstance();
var res1 = responce.data['user'];
var token = res1['token'];
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Navbar()),
);
Fluttertoast.showToast(
msg: "Login Successfull", backgroundColor: Colors.cyan);
return '';
} catch (e) {
Fluttertoast.showToast(
msg: "User Already exists", backgroundColor: Colors.cyan);
return 'some thing wrong';
}
}

I don't know whether it will be the cleanest way or not but you can use REST APIs to get/send data from/to Springboot Server.
For more information: https://medium.com/nerd-for-tech/flutter-series-connecting-ui-to-spring-boot-backend-f9874dc3dcd5
For your Flutter Project structure, you can use BLoC or any other state management.

You can use spring as RestAPI which has logic something like http method(get, post, put, delete..).
(RestfulAPI is used many reason, one of reason is for various client.(mobile, web, pad,..))
You can send data from client to server on query string in uri, header or body.

Related

API - Multitenancy - Works with Postman only

When i login through the flutter client, i receive the previous users content.
I assume this is due to an issue in the logout function.
Everything works fine in Postman(Relevant user content is presented in Postman)
lib\providers\auth_provider.dart
import 'package:demo_app/services/api.dart';
import 'package:flutter/material.dart';
class AuthProvider extends ChangeNotifier {
bool isAuthenticated = false;
late String token;
ApiService apiService = ApiService('');
Future<void> register(String name, String email, String password, String passwordConfirm, String deviceName) async{
token = await apiService.register(name, email, password, passwordConfirm, deviceName);
isAuthenticated = true;
notifyListeners();
}
Future<void> logIn(String email, String password, String deviceName) async {
token = await apiService.logIn(email, password, deviceName);
isAuthenticated = true;
notifyListeners();
}
Future<void> logOut() async {
token = '';
isAuthenticated = false;
notifyListeners();
}
}
The api.dart file looks like this
lib\services\api.dart
class ApiService{
late String token;
ApiService(this.token);
final String baseUrl = 'http://flutter-api.test/api/';
Future<List<Category>> fetchCategories() async {
http.Response response =
await http.get(Uri.parse('${baseUrl}categories'),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
HttpHeaders.acceptHeader: 'application/json',
HttpHeaders.authorizationHeader: 'Bearer $token'
},
);
List categories = jsonDecode(response.body);
return categories.map((category) => Category.fromJson(category)).toList();
}
..
..
Future<String> logIn(String email, String password, String deviceName) async {
String uri = '${baseUrl}auth/login';
http.Response response = await http.post(Uri.parse(uri),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
HttpHeaders.acceptHeader: 'application/json',
},
body: jsonEncode({
'email': email,
'password': password,
'device_name': deviceName
})
);
if(response.statusCode == 422){
Map<String, dynamic> body = jsonDecode(response.body);
Map<String, dynamic> errors = body['errors'];
String errorMessage = '';
errors.forEach((key, value){
value.forEach((element){
errorMessage += element + '\n';
});
});
throw Exception(errorMessage);
}
return response.body;
}
}
The category_privder.dart file looks like this
lib\providers\category_provider.dart
import 'package:demo_app/models/category.dart';
import 'package:demo_app/providers/auth_provider.dart';
import 'package:demo_app/services/api.dart';
import 'package:flutter/material.dart';
class CategoryProvider extends ChangeNotifier{
List<Category> categories = [];
late ApiService apiService;
late AuthProvider authProvider;
CategoryProvider(this.authProvider){
apiService = ApiService(authProvider.token);
init();
}
Future init() async{
categories = await apiService.fetchCategories();
notifyListeners();
}
Future<void> addCategory(String name) async{
try{
Category addedCategory = await apiService.addCategory(name);
categories.add(addedCategory);
notifyListeners();
} catch(e){
await authProvider.logOut();
// ignore: avoid_print
// print(e);
}
}
Future<void> updateCategory(Category category) async{
try{
Category updatedCategory = await apiService.updateCategory(category);
int index = categories.indexOf(category);
categories[index] = updatedCategory;
notifyListeners();
} catch(e){
await authProvider.logOut();
}
}
Future<void> deleteCategory(Category category) async{
try{
await apiService.deleteCategory(category.id);
categories.remove(category);
notifyListeners();
} catch(e){
await authProvider.logOut();
}
}
}
I am trying to get the flutter client to display the relevant categories of a particular user. The Laravel part seems to work well, because everything works fine in Postman
Maybe it is something to do with the BuildContext
How can i solve this issue
lib\screens\login.dart
import 'package:flutter/material.dart';
import 'package:demo_app/providers/auth_provider.dart';
// import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'dart:io';
import 'dart:async';
// import 'dart:developer' as developer;
// import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
class Login extends StatefulWidget{
const Login({super.key});
#override
State<Login> createState() => _LoginState(); // Alternative for _LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final emailController = TextEditingController();
final passwordController = TextEditingController();
String errorMessage = '';
String? deviceName;
#override
void initState() {
super.initState();
getDeviceName();
}
#override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(
title: const Text('Login'),
),
body: Container(
color: Theme.of(context).primaryColorDark,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Card(
elevation: 8,
margin: const EdgeInsets.only(left: 16.0, right: 16.0),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.emailAddress,
controller: emailController,
validator: (String? value){
if(value!.isEmpty){
return 'Enter Email';
}
return null;
},
onChanged: (text) => setState(() => errorMessage = ''),
decoration: const InputDecoration(
labelText: 'Email',
),
),
TextFormField(
obscureText: true,
enableSuggestions: false,
autocorrect: false,
controller: passwordController,
validator: (String? value){
if(value!.isEmpty){
return 'Enter password';
}
return null;
},
onChanged: (text) => setState(() => errorMessage = ''),
decoration: const InputDecoration(
labelText: 'Password',
),
),
ElevatedButton(
onPressed: () => submit(),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 36)
),
child: const Text('Login'),
),
Text(errorMessage, style: const TextStyle(color: Colors.red)),
Padding(
padding: const EdgeInsets.only(top:20.0),
child: InkWell(
onTap: () {
Navigator.pushNamed(context, '/register');
},
child: const Text("Register New User", style: TextStyle(fontSize: 14)),
),
),
],
),
)
),
),
],
),
),
);
}
Future<void> submit() async{
final form = _formKey.currentState;
if(!form!.validate()){
return;
}
final AuthProvider provider = Provider.of<AuthProvider>(context, listen: false);
try {
await provider.logIn(
emailController.text,
passwordController.text,
deviceName ?? 'Some Device'
);
} catch(e){
setState(() {
errorMessage = e.toString().replaceAll('Exception:', '');
});
}
}
Future<void> getDeviceName() async{
final deviceInfoPlugin = DeviceInfoPlugin();
try{
if (Platform.isAndroid){
var build = await deviceInfoPlugin.androidInfo;
setState((){
deviceName = build.model;
});
}
else if (Platform.isIOS){
var build = await deviceInfoPlugin.iosInfo;
setState((){
deviceName = build.model;
});
}
} on PlatformException{
setState((){
deviceName = 'Failed to get platform version';
});
}
}
}

how to upload images in server using flutter and laravel api?

How to upload images in server using flutter with Laravel API? I tried using getx, its returning null. also I have image_picker and image_cropper package in my pubspec.yaml
Select Image from Gallery using File Picker
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
class ImageScreen extends StatefulWidget {
ImageScreen();
#override
State<ImageScreen> createState() => _ImageScreenState();
}
class _ImageScreenState extends State<ImageScreen> {
File file;
Future<File> uploadImage() async {
FilePickerResult result = await FilePicker.platform.pickFiles();
if (result != null) {
setState(() {
file = File(result.files.single.path);
});
print(result.files.single.path);
} else {
// User canceled the picker
}
return file;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () {
uploadImage();
},
child: Container(
color: Colors.green,
padding: EdgeInsets.all(5),
child: Text('Upload Image', style: TextStyle(fontSize: 16, color: Colors.white),)
),
),
);
}
}
Uploading Image to the server using http.multipartFile
static Future<dynamic> uploadImage({File file}) async {
try {
http.MultipartRequest request = new http.MultipartRequest("POST", _uri);
http.MultipartFile multipartFile = await http.MultipartFile.fromPath('file_name', file.path);
request.files.add(multipartFile);
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
if (response.statusCode == 200 ) {
return jsonDecode(response.body);
}
}
catch (e) {
return null;
}
}
final images = <File>[].obs;
Use this method for picking up images
Future pickImage(ImageSource source) async {
ImagePicker imagePicker = ImagePicker();
XFile pickedFile = await imagePicker.pickImage(source: source, imageQuality: 80);
File imageFile = File(pickedFile.path);
print(imageFile);
if (imageFile != null) {
images.add(imageFile);
} else {
Get.showSnackbar(GetSnackBar(message: "Please select an image file"));
}
}
Use this for uploading images to the server with your specific url.As I have used dio for uploading.You can use http as well.
Future<String> uploadImage(File file) async {
String fileName = file.path.split('/').last;
// you can edit it for your own convenience
var _queryParameters = {
'api_token': 'your token if required',
};
Uri _uri = 'Your base url'
var formData = FormData.fromMap({
"file": await MultipartFile.fromFile(file.path, filename: fileName),
});
var response = await dio.post(_uri, data: formData);
print(response.data);
if (response.data['data'] != false) {
return response.data['data'];
} else {
throw new Exception(response.data['message']);
}
}
This works for me, so maybe others might need it as well.
uploadImage(imageFile) async {
var stream = new http.ByteStream(
DelegatingStream.typed(imageFile.openRead()));
var length = await imageFile.length();
var uri = Uri.parse(
'http://192.168.5.196/ApiFileUploadTest/public/api/uploading-file-api');
var request = new http.MultipartRequest('POST', uri);
var multipartFile = new http.MultipartFile('file', stream, length,
filename: basename(imageFile.path));
request.files.add(multipartFile);
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}

How to store image to cachednetwrok image in flutter

I have the following code where I fetch an image from firebase storage as an Image. Now, I want to store this image in my CachedNetworkImage so that I don't have to fetch it every time from the DB. Since the cachednetworkimage expects a URL and I am fetching an Image, how do I use the cachednetworkimage?
Here's my code;
final FirebaseStorage storage = FirebaseStorage(
app: Firestore.instance.app,
storageBucket: 'gs://my-project.appspot.com');
Uint8List imageBytes;
String errorMsg;
_MyHomePageState() {
storage.ref().child('selfies/me2.jpg').getData(10000000).then((data) =>
setState(() {
imageBytes = data;
})
).catchError((e) =>
setState(() {
errorMsg = e.error;
})
);
}
#override
Widget build(BuildContext context) {
var img = imageBytes != null ? Image.memory(
imageBytes,
fit: BoxFit.cover,
) : Text(errorMsg != null ? errorMsg : "Loading...");
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new ListView(
children: <Widget>[
img,
],
));
}
}```
Cached network image and Flutter cache manager
The package Cached network image depends on another package called Flutter cache manager in order to store and retrieve image files.
Flutter cache manager
You need to download your image files and put them in the cache using the package. Here is an example code that gets files and their download urls from Firebase Storage and put them in the cache:
// import the flutter_cache_manager package
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
// ... other imports
class MyCacheManager {
Future<void> cacheImage() async {
final FirebaseStorage storage = FirebaseStorage(
app: Firestore.instance.app,
storageBucket: 'gs://my-project.appspot.com',
);
final Reference ref = storage.ref().child('selfies/me2.jpg');
// Get your image url
final imageUrl = await ref.getDownloadURL();
// Download your image data
final imageBytes = await ref.getData(10000000);
// Put the image file in the cache
await DefaultCacheManager().putFile(
imageUrl,
imageBytes,
fileExtension: "jpg",
);
}
}
Cached network image
Next, you will use CacheNetworkImage widget as it shown in the documentation.
// ... some code
#override
Widget build(BuildContext context) {
return Scaffold(
body: CachedNetworkImage(
imageUrl: "your_image_link_here",
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
);
}
If you put your image files in the cache by using Flutter cache manager, Cached network image should retrieve them from the cache directly. If your image files expire or the cache is cleared somehow, it will download and put them in the cache for you.
Full Example
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
class MyCacheManager {
final _storage = FirebaseStorage(
app: FirebaseFirestore.instance.app,
storageBucket: 'gs://my-project.appspot.com',
);
final defaultCacheManager = DefaultCacheManager();
Future<String> cacheImage(String imagePath) async {
final Reference ref = _storage.ref().child(imagePath);
// Get your image url
final imageUrl = await ref.getDownloadURL();
// Check if the image file is not in the cache
if ((await defaultCacheManager.getFileFromCache(imageUrl))?.file == null) {
// Download your image data
final imageBytes = await ref.getData(10000000);
// Put the image file in the cache
await defaultCacheManager.putFile(
imageUrl,
imageBytes,
fileExtension: "jpg",
);
}
// Return image download url
return imageUrl;
}
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _imageUrl;
#override
void initState() {
final myCacheManager = MyCacheManager();
// Image path from Firebase Storage
var imagePath = 'selfies/me2.jpg';
// This will try to find image in the cache first
// If it can't find anything, it will download it from Firabase storage
myCacheManager.cacheImage(imagePath).then((String imageUrl) {
setState(() {
// Get image url
_imageUrl = imageUrl;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: _imageUrl != null
? CachedNetworkImage(
imageUrl: _imageUrl,
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
)
: CircularProgressIndicator(),
),
);
}
}
Try this way out using firebase_image package. From here . You need to sync with image url (selfies/me2.jpg) and bucket url (gs://my-project.appspot.com)
Image(
image: FirebaseImage('gs://bucket123/userIcon123.jpg'),
// Works with standard parameters, e.g.
fit: BoxFit.fitWidth,
width: 100,
// ... etc.
)
I'm not Fire-store user, but this should work.
It might needs a little modification or something, please share in a comment to update my answer according to that
You can get file object as follow..
import 'dart:io';
import 'dart:typed_data';
Uint8List readyData = imageBytes;
File('my_image.jpg').writeAsBytes(bodyBytes);
and save it using image_gallery_saver, so the code should look like
Future<String> _createFileFromString() async {
final encodedStr = "...";
Uint8List bytes = base64.decode(imageBytes);
String dir = (await getApplicationDocumentsDirectory()).path;
String fullPath = '$dir/abc.png';
print("local file full path ${fullPath}");
File file = File(fullPath);
await file.writeAsBytes(bytes);
print(file.path);
final result = await ImageGallerySaver.saveImage(bytes);
print(result);
return file.path;
}
For your storage instance use some method like so
Future<void> downloadURLExample() async {
String downloadURL = await storage.ref('selfies/me2.jpg')
.getDownloadURL();
// Within your widgets:
// CachedNetworkImage(imageUrl: downloadURL);
}
to get it working with Firebase Storage with included offline functionality I changed it that way
Future<String> cacheImage(String imagePath) async {
var fileinfo = await defaultCacheManager.getFileFromCache(imagePath);
if(fileinfo != null)
{
return fileinfo.file.path;
} else{
final Reference ref = _storage.child(imagePath);
// Get your image url
final imageUrl = await ref.getDownloadURL();
// Check if the image file is not in the cache
// Download your image data
final imageBytes = await ref.getData(10000000);
// Put the image file in the cache
var file = await defaultCacheManager.putFile(
imageUrl,
imageBytes!,
key: imagePath,);
return file.path;
}
}
for anyone still stuck with this.. try this required no hacks and uses CachedNetworkImageProvider built-in retrieval methods.
first screen:
CachedNetworkImage(
imageUrl: "https://whereismyimage.com",
progressIndicatorBuilder:
(context, url, progress) {
return CircularProgressIndicator(
value: progress.progress,
);
},
errorWidget: (context, url, error) => const Icon(Icons.error),
),
then second screen
Image(image: CachedNetworkImageProvider("https://whereismyimage.com)"),
The CachedNetworkImageProvider knows how to retrieve the cached image using the url.
Check out cached_network_image: ^2.5.0 package.
How to use it?
CachedNetworkImage(
imageUrl: "http://via.placeholder.com/350x150",
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),

Load image from sharedPreferences to pdf in Flutter

I'm need to load a image from sharedPreferences to a pdf document.
The image loads normally when in normal use, but i don't know how to make it load in the pdf.
When I try to load it like a normal image I get "Unhandled Exception: type 'Image' is not a subtype of type 'PdfImage'"
This is how I use it normally.
import 'package:flutter/material.dart';
import 'package:flutter_settings_screens/flutter_settings_screens.dart';
import 'package:image_picker/image_picker.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:MyApp/SharedPrefUtility.dart';
Future<void> initSettings() async {
await Settings.init(
cacheProvider: SharePreferenceCache(),
);
}
class ProfilePage extends StatefulWidget {
#override
_ProfilePageState createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
Image logo;
pickImage(ImageSource source) async {
final _image = await ImagePicker.pickImage(source: ImageSource.gallery);
if (_image != null) {
setState(() {
logo = Image.file(_image);
});
ImageSharedPrefs.saveImageToPrefs(
ImageSharedPrefs.base64String(_image.readAsBytesSync()));
} else {
print('Error picking image!');
}
}
loadImageFromPrefs() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final imageKeyValue = prefs.getString(IMAGE_KEY);
if (imageKeyValue != null) {
final imageString = await ImageSharedPrefs.loadImageFromPrefs();
setState(() {
logo = ImageSharedPrefs.imageFrom64BaseString(imageString);
});
}
}
#override
void initState() {
super.initState();
loadImageFromPrefs();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text('Profile Settings'),
),
body: Center(
child: ListView(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
ClipRect(
child: Container(
width: 300,
height: 300,
child: logo == null ? Text('No image selected.') : logo,
),
),
RaisedButton(
onPressed: () {
pickImage(ImageSource.gallery);
},
child: Text('Pick Company Logo'),
),
],
),
],
),
),
);
}
}
With SharedPrefUtility.dart
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/widgets.dart';
import 'package:shared_preferences/shared_preferences.dart';
const IMAGE_KEY = 'IMAGE_KEY';
class ImageSharedPrefs {
static Future<bool> saveImageToPrefs(String value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return await prefs.setString(IMAGE_KEY, value);
}
static Future<String> loadImageFromPrefs() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(IMAGE_KEY);
}
static String base64String(Uint8List data) {
return base64Encode(data);
}
static imageFrom64BaseString(String base64String) {
return Image.memory(
base64Decode(base64String),
fit: BoxFit.contain,
);
}
}
Any Suggestions would be great.
davey06 gave the answer on gitHub
final imageString = await ImageSharedPrefs.loadImageFromPrefs();
// Create a PDF document.
final document = pw.Document();
// Add page to the PDF
document.addPage(pw.Page(build: (context) {
return pw.Center(
child: pw.Image(
PdfImage.file(document.document, bytes: base64Decode(imageString)),
),
);
}));
// Return the PDF file content
return document.save();
https://github.com/DavBfr/dart_pdf/issues/477
"Unhandled Exception: type 'Image' is not a subtype of type 'PdfImage'" - it says you need to convert Image to PdfImage
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart ' as pw;
pdf = pw.Document();
PdfImage pdfImage = PdfImage.fromImage(pdf.document, image: logo);
pdf.addPage(
pw.Page(
pageFormat: PdfPageFormat.a4,
build: (context) {
return pw.Image(arcPdfImage, fit: pw.BoxFit.contain);
},
),
);
I'm using images taken from my assets to create PDF in this way:
PdfImage _logo = PdfImage.file(
doc.document,
bytes: (await rootBundle.load('assets/client-logo.png')).buffer.asUint8List(),
);
//later, during widget tree creation
pw.Image(_logo, width: 180);
It's not exactly what you're doing, but I think it's close enough. The PdfImage class can take as input any Uint8List for the bytes argument, so you should be able to use the same input you're using for the base64String method you defined for ImageSharedPrefs

Use progress bar dialog in async task using Future in Flutter

I want to create common class for execute API. Now i needed to add progress dialog while executing task and after complete task dialog should be dismiss.I google lot but not get appropriate solution So help me to achieve it.
For Http Client i used dio plugin.
Please help me for adding progress dialog in this class so when i create request using this class it added progress dialog while executing task. i create this type of class in java but now i want to add it in flutter.
HttpRequest.dart
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
class HttpRequest {
void post(BuildContext context,String url, dynamic data, HttpListener listener) {
Dio dio = new Dio();
dio.post(url, data: data)
.then((Response<dynamic> response) {
if (response.statusCode == 200) {
listener.onSuccess(response.data);
} else {
listener.onError("Error");
}
})
.catchError((Exception error) {
listener.onError(error.toString());
});
}
}
abstract class HttpListener {
void onSuccess(dynamic result);
void onError(String error);
}
It's better to show progressbar in widgets, not in common classes.
Use below example (using http package):
class HttpRequest {
final JsonDecoder _decoder = new JsonDecoder();
Future post(String url, dynamic data) async {
http.Response response = await http.post(url,body: data);
if(response.statusCode < 200 || response.statusCode > 300){
throw new Exception('Faild');
} else {
return _decoder.convert(response.body);
}
}
}
The button that calls post method:
child: MaterialButton(onPressed: () async {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}));
HttpRequest _util = new HttpRequest();
try{
var res = await _util.post('someurl',_data);
} catch(Exception) {
//Handle Exception
} finally {
Navigator.pop(context);
}
});
I made a public package, future_progress_dialog, which is the opposite concept of package.
You wanted to put progress dialog in the task. But I tried the opposite way, putting Future task into the dialog.
https://pub.dev/packages/future_progress_dialog
With this package you can make a progress dialog like this.
var result = await showDialog(
context: context,
child: FutureProgressDialog(future, 'Loading...'));
I hope this would be helpful.
It is better to do it in fully async mode
onPressed: () async {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}));
authenticate().then((value) {
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => HomePage()));
}).onError((error, stackTrace) {
Navigator.pop(context);
_showErrorToast(context);
});
},

Resources