Flutter how to create package with function - flutter

I'm trying to make a package. I need to use async function, but I can't use it while building package.
Package Code:
class Sozluk {
wiki(ceviri) async {
var res = await http.Client()
.get(Uri.parse('https://sozluk.gov.tr/gts?ara=$ceviri'));
var body = res.body;
var decoded = jsonDecode(body);
var json = decoded[0];
var sozlukanlam = json["anlamlarListe"][0]["anlam"];
print(sozlukanlam);
return sozlukanlam;
}
}
Test Code:
void main() {
test('köpek', () {
final sozluk = Sozluk();
var cevap = sozluk.wiki('köpek');
print(cevap);
});
}
The print I got:
Instance of 'Future<dynamic>'

You code is missing a lot of pieces. Just because Dart allows you to write code like a sloppy web developer, does not mean you should. Dart is strongly typed, that is an advantage, please use it.
Problems:
ceviri has no explicit type.
wiki has no explicit return type.
wiki is not awaited
Your anonymous method is not async.
More information about Futures, async and await: What is a Future and how do I use it?
Fixing your code as good as possible:
class Sozluk {
Future<TYPE_X> wiki(TYPE_Y ceviri) async {
var res = await http.Client()
.get(Uri.parse('https://sozluk.gov.tr/gts?ara=$ceviri'));
var body = res.body;
var decoded = jsonDecode(body);
var json = decoded[0];
var sozlukanlam = json["anlamlarListe"][0]["anlam"];
print(sozlukanlam);
return sozlukanlam;
}
}
Test Code:
void main() {
test('köpek', () async {
final sozluk = Sozluk();
var cevap = await sozluk.wiki('köpek');
print(cevap);
});
}
Please note that you need to fill in TYPE_X and TYPE_Y, I have no idea which datatypes best represent your data. Is it a number? A text? You decide.

Yout question is unclear.
If you need to print
sozlukanlam
var in test function you need to await your wiki function becaus it is async.
So you could do somthing like that:
void main() {
test('köpek', () async {
final sozluk = Sozluk();
var cevap = await sozluk.wiki('köpek');
print(cevap);
});
}
OR, if test function couldn't bee async
void main() {
test('köpek', () {
final sozluk = Sozluk();
sozluk.wiki('köpek').then((sozlukanlam)=>print(cevap));
});
}

Related

Flutter: How to fix setState() callback argument returned a Future error?

My goal is to do a simple BitcoinApp. I am trying to get a method that is in the MyHomePageState class to call a method that I have in another class. When I compile and click on the button to give me the bitcoin info of USD I get the error of setState() callback argument returned to Future. Any advice or alternative that you can suggest me? I'm new to Flutter and adjusting.Here is my code:
///This piece of code is located in MyHomePageState Class
BitcoinCurrency _bitcoin = BitcoinCurrency();
void _getUSDBitcoin(){
setState(() async{
_bitcoin.usdBitcoin();
});
}
///This is the class I have outside of MyHomePageState Class.
class BitcoinCurrency {
///Variables we want for the information
String _disclaimer = "N/A";
String _time = "N/A";
String _currencyBitcoin = "N/A";
///Getters for our variables
get disclaimer => _disclaimer;
get time => _time;
get currencyBitcoin => _currencyBitcoin;
///Methods()
void usdBitcoin() async{
var url = Uri.https('api.coindesk.com', '/v1/bpi/currentprice.json');
var response = await http.get(url);
var httpBody = response.body;
var decoded = json.decode(httpBody);
_disclaimer = decoded['disclaimer'];
_time = decoded['time']['updated'];
_currencyBitcoin = decoded['bpi']['USD']['rate'];
}
}
You can convert usdBitcoin void method to Future<void>
Future<void>? usdBitcoin() async{
var url = Uri.https('api.coindesk.com', '/v1/bpi/currentprice.json');
var response = await http.get(url);
var httpBody = response.body;
var decoded = json.decode(httpBody);
_disclaimer = decoded['disclaimer'];
_time = decoded['time']['updated'];
_currencyBitcoin = decoded['bpi']['USD']['rate'];
}
And call setState like
usdBitcoin().then((value) => setState(() {}));
setState can't be an async function. usdBitcoin has to be a Future method, so you have to call it before the setState starts.
usdBitcoin method:
Future usdBitcoin() async{
var url = Uri.https('api.coindesk.com', '/v1/bpi/currentprice.json');
var response = await http.get(url);
var httpBody = response.body;
var decoded = json.decode(httpBody);
_disclaimer = decoded['disclaimer'];
_time = decoded['time']['updated'];
_currencyBitcoin = decoded['bpi']['USD']['rate'];
}
In initState:
usdBitcoin().then(
(value) => setState(
() {
},
),
)

How to Save List in SharedPreferences in Flutter

Hello all at first I want to mention that I've tried a lot of solutions here but it didn't work for me.
I bring the list from the database through the following code:
var listCat = [];
Future getdata() async {
apiURL = '***************.php';
var response = await http.post(Uri.parse(apiURL));
var responsebody = jsonDecode(response.body);
if (responsebody.length >0){
for (int i = 0; i < responsebody.length; i++) {
listCat.add(responsebody[i]['name']+ ':' + responsebody[i]['image'].toString());
}
return responsebody;
}else{
}
}
As is obvious in the code above I am trying to get the name and image and this is not a problem right now I want to store this listCat in SharedPreferences until I recall it from all pages of the app
I have the following class to save SharedPreferences:
class APIPreferences {
static SharedPreferences ? _preferences;
static const _keyMuinCat = 'MuinCat';
static Future init() async => _preferences = await SharedPreferences.getInstance();
static Future setMuinCat(String MuinCat) async => await _preferences!.setString(_keyMuinCat, MuinCat);
static String? getMuinCat() => _preferences!.getString(_keyMuinCat);
}
Then I save what I need to save by the following line:
APIPreferences.setMuinCat(listCat.toString());
Then I can bring pre-stored data from any location where I need it through the following code:
CatList = APIPreferences.getMuinCat() ?? '';
I tried to do the following thing now to save the list in the first code above:
var listCat = [];
Future getdata() async {
apiURL = '***************.php';
var response = await http.post(Uri.parse(apiURL));
var responsebody = jsonDecode(response.body);
if (responsebody.length >0){
for (int i = 0; i < responsebody.length; i++) {
listCat.add(responsebody[i]['name']+ ':' + responsebody[i]['image'].toString());
APIPreferences.setMuinCat(listCat.toString());
}
return responsebody;
}else{
}
}
But it didn't work. I don't really know how to deal with it.
How can I save it and then bring it to use with ListView.
instead of:
_preferences!.setString(_keyMuinCat, "some string");
use:
_preferences!.setStringList(_keyMuinCat, ["some", "strings", "in", "list"]);
So in your code, the setMuinCat method needs to be:
static Future setMuinCat(List<String> muinCat) async => await _preferences!.setStringList(_keyMuinCat, muinCat);
and then you call it like this:
APIPreferences.setMuinCat((listCat as List).map((v) => v.toString()).toList());
To save the list in shared preferences you need to pass as jsonEncode(yourList data) and when you will fecth the shared list you will again jsonDecode(your list)
await prefs.setString('YOUR KEY', json.encode(YOURMAP()));

Not able to print debug message while unit testing in Flutter

I am testing a pretty straightforward use-case in Flutter. Inside the use-case class, I have a function that I'm invoking from my test. And I want to add some debug print statements to print the value of some variables inside the function of use-case. But it's not getting printed anywhere. How can I achieve this?
The function in Use-case.
Future<Either<Failure, List<Contest>>> call(NoParams params) async {
final result = await repository.getAllContests();
final currentDateTime = DateTime.now();
List<Contest> ongoingContests = [];
result.fold(
(l) => throw ServerException(),
(allContestList) => () {
for (var contest in allContestList) {
var contestStartTime = DateTime.parse(contest.start_time);
var contestEndTime = DateTime.parse(contest.end_time);
print(contestEndTime); //print statement
}
});
return Right(ongoingContests);
}
}
The test function
test('Should return only the ongoing contests', () async {
when(mockHomepageRepository.getAllContests()).thenAnswer((_) async =>
const Right([tContest, tOngoingContest, tUpcomingContest]));
final result = await getOngoingContests(NoParams()); //invoking the function
expect(result, const Right([tOngoingContest]));
verify(mockHomepageRepository.getAllContests());
verifyNoMoreInteractions(MockHomepageRepository());
});

Exception in json.decode : Closure: () => String from Function 'toString'

I am getting some data from API in flutter. I am trying to decode the data using json.decode() but this decode function gives me the following error:
Closure: () => String from Function 'toString'
Here's my code:
Future<Product> createOrder() async {
var client = new http.Client();
var productModel = null;
try {
var response = await client
.get(Uri.https('butterbasket.onrender.com', Strings.createOrderUrl));
if (response.statusCode == 200) {
var body = response.body;
print("Body: $body");
var jsonMap = json.decode(body);
var productModel = Product.fromJson(jsonMap);
}
} catch (e) {
print("Exception: ${e.toString}");
}
return productModel;
}
Here is the Error Debug Console:
You are running into issues because the data you are loading in is an array, but the model is an object. You'll need to do something like the following:
final List jsonProducts = json.decode(body)
final List<Product> products =
jsonProducts.map((jsonProduct) => Product.fromJson(jsonProduct)).toList();
and then if you only need the first item you can do:
final Product product = products[0]
But don't forget to check if the array is big enough.
Your Future function must return an optional Product?, otherwise your future will never find a result as you are declaring it inside the function.
Instead of:
Future<Product> createOrder() async {}
Use:
Future<Product?> createOrder() async {}
Finally your async snapshot and FutureBuilder type should be of type <Product?>.

Waiting async/await function totally

In the beginning of system ,I need to load the xml file.
I use async/await to wait for rootBundle.loadString finish.
However in this case, print ("I can wait rootBundle here"); is executed after rootBundle.loadString finish, runApp(MyApp()) starts before finished.
Is there a way to execute runApp() after rootBundle.loadString finish
Because my whole setting is written in one xml files. so I want to make sure to load before first building.
void main(){
inter = new Internationalize();
inter.init();
runApp(MyApp());
}
class Internationalize{
var intls = {};
var xmlBody;
void init(){
print("internationalize class start");
rootBundle.loadString('assets/i18n/en/strings.xml').then(
(String contents) {
var document = xml.parse(contents);
xmlBody = document.findAllElements('string');
print("load finish");
});
print ("I can wait rootBundle here");
}
}
void main() async { // mark it async
WidgetsFlutterBinding.ensureInitialized(); // mandatory since Flutter 1.9 if you're making this method async
inter = new Internationalize();
await inter.init(); // await here
runApp(MyApp());
}
class Internationalize {
var intls = {};
var xmlBody;
Future<void> init() async { // make it Future<void>
print("internationalize class start");
String contents = await rootBundle.loadString('assets/i18n/en/strings.xml'); // await on loadString
var document = xml.parse(contents);
xmlBody = document.findAllElements('string');
print("load finish");
print("I can wait rootBundle here");
}
}
This is the same answer as given by #CopsOnRoad with some explanation.
You should separate the use of future response rootBundle.loadString().
try following:
String contents = await rootBundle.loadString('assets/i18n/en/strings.xml');
var document = xml.parse(contents);
xmlBody = document.findAllElements('string');
print("load finish");
Note: you'll need to add async modifier in all methods, even in the main method as well and add await before every method call.
i.e.:
void main(){
...
await inter.init();
...
}
...
Future<void> init async {
String contents = await rootBundle.loadString('assets/i18n/en/strings.xml');
var document = xml.parse(contents);
xmlBody = document.findAllElements('string');
print("load finish");
}