Flutter cache mechanism for Dio retrofit sub library - flutter

i my application i'm using Dio's Retrofit sub library, and inside that i'm not sure how can i define cache mechanism for that,
i found this line in Retrofit sample code:
#GET("")
Future<String> testCustomOptions(#DioOptions() Options options);
now how can i define cache on this http request?
Retrofit documentation:
void main(List<String> args) {
final dio = Dio(); // Provide a dio instance
dio.options.headers["Demo-Header"] = "demo header"; // config your dio headers globally
final client = RestClient(dio);
client.getTasks().then((it) => logger.i(it));
dio-http-cache documentation:
QuickStart
Add a dio-http-cache interceptor in Dio :
dio.interceptors.add(DioCacheManager(CacheConfig(baseUrl: "http://www.google.com")).interceptor);
Set maxAge for a request :
Dio().get(
"http://www.google.com",
options: buildCacheOptions(Duration(days: 7)),
);
my full implemented code:
Provider(
create: (_) => MyApis.create(),
),
abstract class MyApis{
factory MyApis(Dio dio, {String baseUrl}) = _MyApis;
#GET("/login")
Future<HttpResponse<PageInformation>> login(#DioOptions() Options options);
static MyApis create() {
final dio = Dio();
dio.options.headers['Content-Type'] = 'application/json';
dio.options.receiveTimeout = 60000;
dio.options.connectTimeout = 120000;
return _MyApis(dio);
}
}

Add Parameter in your API Add point Call
Future<HttpResponse<PageInformation>> login(#DioOptions() Options options);
Add Interceptor in Dio
dio.interceptors.add(DioCacheManager(CacheConfig(baseUrl: 'YOUR BASE URL')).interceptor);
Create an object for Endpoint argument
Options options = buildCacheOptions(Duration(days: 10),forceRefresh: true);
Call your API End point
myapi.login(options)

Related

XMLHttpRequest on Flutter Dio Package with Spring Boot server

I'm trying to make a request to my server with a Flutter Web Application using Dio package. It's returning the XMLHttpRequest error but the server is receveing the request normally.
I'm aware that with disable security command the problem vanish, but I need a solution for production as weel.
Dio code:
import 'package:dio/dio.dart';
import '../interceptor/api_interceptor.dart';
class DioApi {
static String backendUrl = "http://localhost:8080/api/";
static Dio _getDio({Map<String, dynamic>? headers}) {
BaseOptions baseOptions = BaseOptions(
baseUrl: backendUrl,
receiveDataWhenStatusError: true,
connectTimeout: 60 * 1000,
receiveTimeout: 60 * 1000,
);
if (headers != null) {
baseOptions.headers.addAll(headers);
}
Dio dio = Dio(baseOptions);
dio.interceptors.add(ApiInterceptor());
return dio;
}
static Future<Response> get(
String url,
{Map<String, dynamic>? headers, Map<String, dynamic>? queryParameters}) async {
return _getDio(headers: headers).get(url, queryParameters: queryParameters);
}
static Future<Response> post(
String url,
dynamic data,
{Map<String, dynamic>? headers, Map<String, dynamic>? queryParameters}) async {
return _getDio(headers: headers).post(url, data: data, queryParameters: queryParameters);
}
}
--disable-web-security can't help me and CORS on server side seems fine.

How to set timeout for Api call using retrofit in flutter?

Where we can set timeout in below code?
As you can see I am using retrofit for api call.
Dio Object
class DioObject{
static Dio getDio(){
debugPrint("Bearer:- ${PrefHelper().pref?.getString(PrefHelper.AUTHORIZATION)}");
final dio = Dio(); // Provide a dio instance
dio.options.headers["Authorization"] =
"Bearer ${PrefHelper().pref?.getString(PrefHelper.AUTHORIZATION)}"; // config your dio headers globally
dio.options.headers["Content-Type"] =
"application/json;charset=UTF-8"; // config your dio headers globally
return dio;
}
}
Api call
final client = RestClient(DioObject.getDio());
var response = await client.xyz();
Rest API
#RestApi(baseUrl: "*****/api")
abstract class RestClient {
factory RestClient(Dio dio, {String baseUrl}) = _RestClient;
#GET("/UserAccessPoints/")
Future<CommonResponse> xyz();
}
You can do it the same way you added your custom headers, or doing it all at once with a BaseOptions object
final dio = Dio();
//Dio Options
dio.options = BaseOptions(
contentType: 'application/json',
connectTimeout: 4000,
sendTimeout: 4000,
receiveTimeout: 10000,
headers : ...
);

How to update a get it instance in flutter?

I am using the getIt package to create instances in my application.
instance.registerLazySingleton<DioFactory>(() => DioFactory(instance()));
// app service client
final dio = await instance<DioFactory>().getDio();
instance.registerLazySingleton<AppServiceClient>(() => AppServiceClient(dio));
Above code is for initialising the instances.
The getDio() function:
Future<Dio> getDio() async {
Dio dio = Dio();
int _timeOut = 60 * 1000; // 1 min
String language = await _appPreferences.getAppLanguage();
Map<String, String> headers = {
CONTENT_TYPE: APPLICATION_JSON,
ACCEPT: APPLICATION_JSON,
AUTHORIZATION: Constants.token,
DEFAULT_LANGUAGE: language
};
dio.options = BaseOptions(
baseUrl: Constants.baseUrl,
connectTimeout: _timeOut,
receiveTimeout: _timeOut,
headers: headers);
if (kReleaseMode) {
} else {
dio.interceptors.add(PrettyDioLogger(
requestHeader: true, requestBody: true, responseHeader: true));
}
return dio;
}
When I build my application for the first time the Constants.token has a blank value.
But in the middle of the application I wish to add a value into it. I am able to change that value but when I see the logs from dio logger it still displays the empty string in the "Authorisation" field.
How do I update my instance so that I can change my token value for my API requests?
you have to register your dio with registerFactory to getit. In your case you are registering as singleton, that's why it is giving you same instance
First you should create an interceptor that call TokenInterceptor with override onRequest method. Inside onRequest method you can modify your headers like below:
https://i.stack.imgur.com/T6PFR.png
And final step you only add to your dio interceptor like that:
dio.interceptors.add(TokenInterceptor());
final getIt = GetIt.instance;
void setupSingleton(){
getIt.allowReassignment=true;
}
//this should call first and then it will work

Dio Cancel current running API before starting a new API request

I am using DIO package for API request but the issue is that when I request for another API while the first API is still in progress.
It doesn't cancel the first request. Both the APIs run simultaneously which is not the desired in my app scenario.
class DioClient {
static BaseOptions options = BaseOptions(baseUrl: baseUrl);
Dio _dio = Dio(options);
Future<dynamic> postFormData(
{dynamic data, String url, dynamic header}) async {
final data1 = data;
var formData = FormData.fromMap(data1);
try {
var response = await _dio.post(url,
options: Options(headers: header), data: formData);
return response.data;
} catch (e) {
throw e;
}}}
If you want to cancel the API request call then you need to use the cancel token provided by DIO.
You need to pass cancel token in dio request when you make other API call use that cancel token to cancel the API request
Here is the code
class DioClient {
static BaseOptions options = BaseOptions(baseUrl: baseUrl);
//Here is line you need
CancelToken cancelToken=CancelToken();
Dio _dio = Dio(options);
Future<dynamic> postFormData(
{dynamic data, String url, dynamic header}) async {
final data1 = data;
var formData = FormData.fromMap(data1);
try {
//pass cancel token here
var response = await _dio.post(url,
options: Options(headers: header), data: formData,cancelToken: cancelToken);
return response.data;
} catch (e) {
throw e;
}}}
And use that cancelToken to cancel the API request when you call another API first you cancel the previous request.
cancelToken.cancel();
Enjoy!

Global configuration (interceptor) for dio in Flutter

First time with Flutter. I'm using dio to send HTTP requests, and I have to add a header to all requests, which I do with an interceptor, like this:
Dio dio = new Dio();
dio.interceptors.add(InterceptorsWrapper(
onRequest:(RequestOptions options) async {
options.headers["X-Requested-With"] = "XMLHttpRequest";
})
);
It works in main.dart, but if I want to import another class like MyHomePage.dart and do HTTP requests there, I'd have to redefine the interceptor in that class too.
How can I implement this interceptor for my whole application without adding it in every .dart file?
Create a function that houses the DIO and then call it where needed
Dio getDio() {
Dio dio = new Dio();
dio.interceptors.add(InterceptorsWrapper(onRequest: (RequestOptions options) async {
options.headers["X-Requested-With"] = "XMLHttpRequest";
}));
return dio;
}
This worked good for me, without interceptors, just create a class and use it in your app.
import 'package:dio/dio.dart';
import '../helpers/api_url.dart';
class dioClient {
Dio dio = Dio();
static Dio simpleDio() {
return Dio(BaseOptions(
baseUrl: apiUrl(),
headers: {'Content-Type': 'application/json; charset=UTF-8'}));
}
static Dio dioWithCookie(String cookie) {
return Dio(BaseOptions(baseUrl: apiUrl(), headers: {
'Content-Type': 'application/json; charset=UTF-8',
'Cookie': cookie
}));
}
}