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
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
}
}
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.
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;
}
}
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.
},
)
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;
}