How can I store the values ​of the json or request in a variable without using future builder or list builder in flutter? - flutter

I want to use the information I get from the json or request and be able to use it in a useraccountheader drawer but WITHOUT, using a list builder or future builder.
I usually use a future builder and display the information from the database.
I want to get the json or request information and store it in a variable or use it directly in a text widget.
It is also to have loaded user information.
In the infoinitialuser2 list, the values ​​of the json or request are stored and I show them in the list builder or future builder, but as I just mentioned, I don't want to do it that way.
code::
Class State<NombreCabeceraDrawer> extends StatefulWidget{return nombrecabeceradrawer()}
class nombrecabeceradrawer extends State<NombreCabeceraDrawer> {
verride
void initState() {
cabeceradrawerservices.MostrarInfoInicialUser().then((value) {
setState(() {
info.addAll(value);
});
} );
super.initState();
}
UserAccountsDrawerHeader(
accountName: Text("here i want to show the value of the json or request"),
accountEmai: Text("here i want to show the value of the json or request too")
),
}
-------------------
class InfoUsuarioInicialServices{
Future MostrarInfoInicialUser() async{
Map<String, String> headers = {
'Content-Type':'application/json;charset=UTF-8',
'Charset':'utf-8'
};
var Url= Uri.parse("http://");
final response = await http.get((Url),headers: headers);
print(response.body);
return productInfoUsuarioInicialromJson(response.body);
}
}
---------------------
List productInfoUsuarioInicialromJson(String str) => List<InfoInicialUserModel>.from(json.decode(str).map((x) => InfoInicialUserModel.fromJson(x)));// con esto hago el get
class InfoInicialUserModel{
String UsuarioPk;
String FotoUsuario;
String CorreoUsuario;
String NombreUsuario;
InfoInicialUserModel({this.UsuarioPk,this.FotoUsuario,this.NombreUsuario,this.CorreoUsuario});
factory InfoInicialUserModel.fromJson(Map<String, dynamic> parsedJson){
return InfoInicialUserModel(
UsuarioPk: parsedJson['Usuari'],
FotoUsuario:parsedJson['image'],
NombreUsuario: parsedJson['Usuario_A'],
CorreoUsuario:parsedJson['Usuario_C']
);
}
}

This is how I would do it:
Future GetMostrarInfoInicialUser() async {
Map<String, String> headers = {
'Content-Type': 'application/json;charset=UTF-8',
'Charset': 'utf-8'
};
var Url = Uri.parse("http://");
final response = await http.get((Url), headers: headers);
if (response.statusCode == 200) {
print(response.body);
var jsonData = json.decode(response.body);
if (jsonData == "Error") {
} else {
if (mounted) {
setState(() {
accountEmail = jsonData['accountEmail'];
accountName = jsonData['accountName'];
});
}
}
}
}
#override
void initState() {
GetMostrarInfoInicialUser();
}

Related

How to fetch data without retrieve to widgets in flutter?

In my code I want fetch data to backend without show in ui. Data getting from API, andaslo for that I use model class that same model and API call I used to fetch data and show in UI. That's work without any errors.But in this page I want get doctor_in vale is true or false from that same model and API call method.
model class
class DataDoctor {
String appId;
String channelName;
String receiver_name;
bool doctor_in;
DataDoctor(
{required this.appId,
required this.channelName,
required this.receiver_name,
required this.doctor_in});
factory DataDoctor.fromJson(Map<String, dynamic> json) {
return DataDoctor(
appId: json['appId'] == null ? null : json['appId'],
channelName: json['channelName'] == null ? null : json['channelName'],
receiver_name:
json['receiver_name'] == null ? null : json['receiver_name'],
doctor_in: json['doctor_in'] == null ? null : json['doctor_in'],
);
}
}
using this model I want get doctor_in boolean value
to the getDoctorActive() method
getDoctorActive() method
void getDoctorActive() {
Map<String, dynamic> jsonData =
json.decode(jsonDataAsString) as Map<String, dynamic>;
doctor_in.value = jsonData['doctor_in'].toString(); }
error
How to get data without show in UI in flutter?
API code
import 'dart:convert';
import 'package:http/http.dart';
import '../model/appIdModel.dart';
class ApiService {
loadData(String channelName) async {
final String url ='https://jsonplaceholder.typicode.com/posts/1=$channelName';
Future<List<Data>> getData() async {
Response response = await get(Uri.parse(url));
if (response.statusCode == 2000) {
Map<String, dynamic> json = jsonDecode(response.body);
List<dynamic> body = json['data'];
List<Data> datas = body.map((dynamic item) => Data.fromJson(item).toList();
return datas;
} else {
throw ('cannot fetch data');
}
}
}
}
initState
Timer? timer;
bool doctor_in = false;
#override
void initState() {
super.initState();
getDoctorActive();
timer =
Timer.periodic(Duration(seconds: 15), (Timer t) => checkDoctorActive());
}
checkDoctorActive
Future<void> checkDoctorActive() async {
if (doctor_in == true) {
future = client.getData(widget.channelName);
}
}
errors
API call
If you want to periodically fetch data in the background without updating the UI, you can create a class for that purpose, like this
class DoctorCheck{
Future<bool> isDoctorActive(String channelName) async {
// do the api call here as shown in the line below
// var jsonResponse = await client.getData(widget.channelName)
return Data.fromJson(jsonResponse).doctor_in == true;
}
}
And call it wherever you want, like this
bool isDoctorActive = await DoctorCheck().isDoctorActive(channelName);
It will return a bool whether the doctor is active or not.
Put it in a function like this
Future<void> dr() async {
bool isDrActive = await DoctorCheck().isDoctorActive(channelName);
setState(() { doctor_in = isDrActive; });
}
Whenever you call dr(), your variable doctor_in will be updated with the latest value of whether doctor is active or not.
From #rrttrr answer with a change
class DoctorCheck{
Future<bool> isDoctorActive(String channelName) async {
return Data.fromJson(json).doctor_in == true; // Change jsonResponse to json
}
}

How to fetch an array data from API and map it to the dart object?

I'm trying to use Flutter documentation to map an array data (comes from API) to the dart object. The documentation uses a single Json object, not an array. I have the following codes:
Json data:
[
{
"channelId" : 1
"channelTitle" : "Photos"
"channelImage" : pr01.jpg
"channelLastPost" : null
"lastUpdate" : null
"userRef" : 1
},
{
"channelId" : 2
"channelTitle" : "Science"
"channelImage" : pr02.jpg
"channelLastPost" : "For test ...."
"lastUpdate" : "2023-01-03"
"userRef" : 1
}
]
ChannelListModel.dart:
class ChannelListModel {
String creator;
String? image;
String title;
String lastPost;
String lastUpdate;
ChannelListModel(
{required this.creator,
required this.image,
required this.title,
required this.lastPost,
required this.lastUpdate});
factory ChannelListModel.fromJson(Map<String, dynamic> json) {
return ChannelListModel(
creator: json['userRef'],
image: json['channelImage'],
title: json['channelTitle'],
lastPost: json['channelLastPost'],
lastUpdate: json['lastUpdate']);
}
Map<String, dynamic> toJson() {
return {
"userRef" : creator,
"channelImage" : image,
"channelTitle" : title,
"channelLastPost" : lastPost,
"lastUpdate" : lastUpdate
};
}
}
HttpRequest.dart:
class HttpServices {
Future<List<ChannelListModel>> getChannelList() async {
var url = base.BaseURL.channelListUrl;
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return List<ChannelListModel>.fromJson(jsonDecode(response.body)); //I have problem in this line
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
}
ChannelPage.dart:
class _ChannelsState extends State<Channels> {
List<ChannelListModel> channels = [];
#override
void initState() {
super.initState();
channels = getChannelsFromHttp(); // A valid array object needs to be provided here.
}
getChannelsFromHttp()async{
var httpService = HttpServices();
var result = await httpService.getChannelList();
return result;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: channels.length,
itemBuilder: (context, index) =>
ChannelCard(channelModel: channels[index]),
),
);
}
}
I want to classify my codes so I decided to provided different dart files for each part. How can I fix my code?
Instead of
returnList<ChannelListModel>.fromJson(jsonDecode(response.body));
Try this code,
List<ChannelListModel> channels = [];
final res = jsonDecode(response.body);
channels.addAll(List<ChannelListModel>.from(
(res).map((x) => ChannelListModel.fromJson(x))));
return channels;
Added based on comments
#override
void initState() {
super.initState();
getChannelsFromHttp();
}
getChannelsFromHttp()async{
var httpService = HttpServices();
var result = await httpService.getChannelList();
setState((){
channels = result;
});
}
Your fromJson factory returns single ChannelListModel.
You can't use List<ChannelListModel>.fromJson. Instead iterate through List and convert each json to ChannelListModel
class HttpServices {
Future<List<ChannelListModel>> getChannelList() async {
var url = base.BaseURL.channelListUrl;
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
//return List<ChannelListModel>.fromJson(jsonDecode(response.body));
final data = jsonDecode(response.body) as List<dynamic>;
return data.map((e) => ChannelListModel.fromJson(e as Map<String, dynamic>))
.toList();
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
}
You can modify the ChannelListModel.fromJson method to handle a list of JSON objects instead of a single object. Here's one way to do it:
factory ChannelListModel.fromJson(List<dynamic> jsonList) {
return jsonList.map((json) => ChannelListModel(
creator: json['userRef'],
image: json['channelImage'],
title: json['channelTitle'],
lastPost: json['channelLastPost'],
lastUpdate: json['lastUpdate'])
).toList();
}
You can also use jsonDecode to convert the response body to a List and then use the above method to convert the list to ChannelListModel
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
final jsonData = jsonDecode(response.body);
return ChannelListModel.fromJson(jsonData);
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
Also, you need to update the getChannelsFromHttp function to assign the result of httpService.getChannelList() to channels variable instead of calling the function again.
#override
void initState() {
super.initState();
getChannelsFromHttp();
}
getChannelsFromHttp() async {
var httpService = HttpServices();
channels = await httpService.getChannelList();
setState(() {});
}
This should solve the problem in your code.

Dependency Injection In Flutter Clean Architecture with Provider State Management

I am trying to wrap my head around clean architecture and I'd be grateful if someone could explain to me how to implement dependency injection in a flutter front end, and give me a basic idea of why it's useful.
I've been trying to make it work with get_it but there's so much info out there it just overwhelming so maybe if I could get one explanation on how to do this in the following case, I'd appreciate that very much.
Just a quick thank you in advance for reading through the below code.
member_remote_data.dart file inside data layer:
abstract class MemberRemoteDataSource {
Future create({required Map<String, dynamic> member});
}
class MemberRemoteDataSourceImpl implements MemberRemoteDataSource {
final http.Client _client = http.Client();
final String _apiHost = Environment().config!.apiHost;
#override
Future create({required Map<String, dynamic> member}) async {
final String url = "$_apiHost/api/member/create";
final Uri uri = Uri.parse(url);
final Map<String, String> headers = {
'Content-Type': 'application/json',
};
final http.Response response = await _client.post(
uri,
headers: headers,
body: member['type'] == 1
? ParentModel.toJson(member)
: ChildModel.toJson(member),
);
if (response.statusCode >= 200 && response.statusCode < 300) {
return jsonDecode(response.body);
} else if (response.statusCode == 422) {
return ValidationError(error: response.body);
} else if (response.statusCode == 404) {
return HttpPageNotFoundError();
} else if (response.statusCode == 500) {
return HttpInternalServerError();
} else if (response.statusCode == 400) {
return HttpBadRequestError(error: response.body);
}
}
}
member_repositroy_impl.dart file inside data layer:
class MemberRepositoryImpl implements MemberRepository {
MemberRepositoryImpl({required this.memberRemoteDataSource});
final MemberRemoteDataSource memberRemoteDataSource;
#override
Future create({required Map<String, dynamic> member}) async {
return await memberRemoteDataSource.create(member: member);
}
}
member_repository.dart file inside domain layer:
abstract class MemberRepository {
Future create({required Map<String, dynamic> member});
}
create_member.dart use case file inside domain layer:
class CreateMember implements UseCase {
CreateMember({required this.memberRepository});
final MemberRepository memberRepository;
#override
Future create({required Map<String, dynamic> member}) async {
return await memberRepository.create(member: member);
}
}
Now, inside the presentation layer, I have my change notifiers where I want to "connect" all of the above together.
How do I do that? How do I add those parameters in a way that makes sens in clean architecture?
enum NotifierState { initial, loading, loaded }
class MemberNotifier extends ChangeNotifier {
// How do I "connect" everything together
// here to show this on the front end?
final UseCase createMember = CreateMember();
NotifierState _notifierState = NotifierState.initial;
NotifierState get notifierState => _notifierState;
void _setState(NotifierState notifierState) {
_notifierState = notifierState;
notifyListeners();
}
String? _emailAlreadyExists;
String? get emailAlreadyExists => _emailAlreadyExists;
void setFailure(emailAlreadyExists) {
_emailAlreadyExists = emailAlreadyExists;
notifyListeners();
}
Future create({required Map<String, dynamic> member}) async {
// _setState(NotifierState.loading);
var body = await createMember.create(member: member);
if (body is ValidationError) {
setFailure(body.emailAlreadyExists());
_setState(NotifierState.loaded);
} else {}
_setState(NotifierState.loaded);
return body;
}
}

how to set values in initState method using riverpod

right now i have a ChangeNotifierProvider, and i want to set some values straight in the initState method.
those values come from a backend API, that are retrieved in that provider.
I am stuck is this situation for a while now, hope i can get some help.
Here is the ChangeNotifierProvider
final userProvider = ChangeNotifierProvider.autoDispose.family<UserProxy, String>((ref, id) {
var notifier = UserProxy(userId: id);
notifier.load();
return notifier;
});
class UserProxy extends ChangeNotifier {
String userId;
User? user;
UserProxy({this.userId = ""});
void load() async {
await getUser().then((value) => generateObject(value));
}
Future<String> getUser() async {
Map<String, String> queryParams = {
"id": userId,
};
var url = Uri.https("asdadas.asdasd.com", "endpoint", queryParams);
Map<String, String> headers = {
'content-type': "application/json",
};
var response = await http.get(url,
headers: headers,);
print(response.body);
return response.body;
}
User generateObject(String jsonString) {
this.user = User.fromJson(jsonDecode(jsonString));
notifyListeners();
return this.user ?? User();
}
}
For this case I would suggest
FutureProvider.autoDispose.family<UserProxy, String>((ref, id) async { .... })
then change your StateWidget to ConsumerStatefulWidget and ConsumerState<>
then
ref.watch(provider(11)).when(
loading: (){},
error: (Object err, StackTrace? st){ },
data: (user){
// build widget with result here.
},
)

Generic deserialization in Flutter / Dart

I'm trying to write a HTTP driver class that takes in a generic class and deserializes the response. I haven't found a good, clean way to do this in Flutter.
I've defined datamodel classes like this:
class MyClass {
String field1;
String field2;
MyClass.fromJson(Map<dynamic, dynamic> json)
: field1 = json["field1"],
field2 = json["field2"];
}
This works well and good if I do it manually...
MyClass makeRequest() {
Response response = http.get(url);
MyClass class = MyClass.fromJson(jsonDecode(response.body));
return class;
}
What I want, is to make a generic HTTP driver like this:
void makeRequest<T>() {
Response response = http.get(url);
T parsed = T.fromJson(jsonDecode(response.body));
return parsed;
}
Is there a way to do this in Flutter/Dart? I've been trying to figure out the right syntax to use a base class and extends but haven't gotten it. Any ideas?
This is what I usually use in my network call, feel free to use. Btw, I recommend the dio package for convenient headers and params config, as well as other error handling features.
// Define an extension
extension BaseModel on Type {
fromJson(Map<String, dynamic> data) {}
}
// For single object
Future<T> makeGetRequest<T>({String url, Map<String, dynamic> params}) {
return http
.get(buildUrl(url, params)) // Don't need the buildUrl() if you use Dio
.then((response) => handleJsonResponse(response))
.then((data) => T.fromJson(data));
// For list of object
Future<List<T>> makeGetRequestForList<T>({String url, Map<String, dynamic> params}) {
return http
.get(buildUrl(url, params)) // Don't need the buildUrl() if you use Dio
.then((response) => handleJsonResponse(response))
.then((data) => List<T>.from(data.map((item) => T.fromJson(item)));
}
// Helper classes without Dio
String buildUrl(String url, [Map parameters]) {
final stringBuilder = StringBuffer(url);
if (parameters?.isNotEmpty == true) {
stringBuilder.write('?');
parameters.forEach((key, value) => stringBuilder.write('$key=$value&'));
}
final result = stringBuilder.toString();
print(result);
return result;
}
// With Dio, you can simply do this:
final res = await API().dio
.get(url, queryParameters: params) // Don't need the [buildUrl] here
.then((response) => handleJsonResponse(response))
.then((data) => T.fromJson(data));
// Handle JSON response
handleJsonResponse(http.Response response, [String endpoint = '']) {
print(
'API: $endpoint \nCODE: ${response.statusCode} \nBODY: ${response.body}');
if (_okStatus.contains(response.statusCode)) {
return jsonDecode(response.body);
}
if (response.statusCode == HttpStatus.unauthorized) {
throw Exception(response.statusCode);
} else {
throw Exception("HTTP: ${response.statusCode} ${response.body}");
}
}
Usage:
// Example class
class Post {
final String title;
Post({this.title});
#override
Post.fromJson(Map<String, dynamic> data) : title = data['title'];
}
// Use the function
Future<Post> getPost() async {
final result = await makeGetRequest<Post>(params: {'post_id': 1});
return result;
}