V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
trevorwang
V2EX  ›  Flutter

照着 retrofit 撸了一个 Dart & Flutter http 库,欢迎 PR https://github.com/trevorwang/retrofit.dart

  •  1
     
  •   trevorwang ·
    trevorwang · 2020-02-10 11:00:28 +08:00 · 6336 次点击
    这是一个创建于 1508 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Retrofit For Dart

    Pub Dart CI CircleCI Build Status

    retrofit.dart is a type conversion dio client generator using source_gen and inspired by Chopper and Retrofit.

    Usage

    Generator

    Add the generator to your dev dependencies

    dependencies:
      retrofit: any
      logger: any  #for logging purpose
    
    dev_dependencies:
      retrofit_generator: any
      build_runner: any
    

    Define and Generate your API

    import 'package:json_annotation/json_annotation.dart';
    import 'package:retrofit/retrofit.dart';
    import 'package:dio/dio.dart';
    
    part 'example.g.dart';
    
    @RestApi(baseUrl: "https://5d42a6e2bc64f90014a56ca0.mockapi.io/api/v1/")
    abstract class RestClient {
      factory RestClient(Dio dio, {String baseUrl}) = _RestClient;
    
      @GET("/tasks")
      Future<List<Task>> getTasks();
    }
    
    @JsonSerializable()
    class Task {
      String id;
      String name;
      String avatar;
      String createdAt;
    
      Task({this.id, this.name, this.avatar, this.createdAt});
    
      factory Task.fromJson(Map<String, dynamic> json) => _$TaskFromJson(json);
      Map<String, dynamic> toJson() => _$TaskToJson(this);
    }
    
    

    then run the generator

    # dart
    pub run build_runner build
    
    # flutter	
    flutter pub run build_runner build
    

    Use it

    import 'package:logger/logger.dart';
    import 'package:retrofit_example/example.dart';
    import 'package:dio/dio.dart';
    
    final logger = Logger();
    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));
    

    More

    Type Conversion

    Before you use the type conversion, please make sure that a factory Task.fromJson(Map<String, dynamic> json) must be provided for each model class. json_serializable is the recommanded to be used as the serialization tool.

    ...
    @GET("/tasks")
      Future<List<Task>> getTasks();
    }
    
    @JsonSerializable()
    class Task {
      String name;
      Task({this.name});
      factory Task.fromJson(Map<String, dynamic> json) => _$TaskFromJson(json);
    }
    

    HTTP Methods

    The HTTP methods in the below sample are supported.

      @GET("/tasks/{id}")
      Future<Task> getTask(@Path("id") String id);
    
      @PATCH("/tasks/{id}")
      Future<Task> updateTaskPart(
          @Path() String id, @Body() Map<String, dynamic> map);
    
      @PUT("/tasks/{id}")
      Future<Task> updateTask(@Path() String id, @Body() Task task);
    
      @DELETE("/tasks/{id}")
      Future<void> deleteTask(@Path() String id);
    
      @POST("/tasks")
      Future<Task> createTask(@Body() Task task);
    
      @POST("http://httpbin.org/post")
      Future<void> createNewTaskFromFile(@Part() File file);
    
      @POST("http://httpbin.org/post")
      @FormUrlEncoded()
      Future<String> postUrlEncodedFormData(@Field() String hello);
    

    Get orignal HTTP reponse

      @GET("/tasks/{id}")
      Future<HttpResponse<Task>> getTask(@Path("id") String id)
    
      @GET("/tasks")
      Future<HttpResponse<List<Task>>>> getTasks()
    

    HTTP Header

    • Add a HTTP header from the parameter of the method

      	@GET("/tasks")
        Future<Task> getTasks(@Header("Content-Type") String contentType );
      
    • Add staitc HTTP headers

      	@GET("/tasks")
      	@Headers(<String, dynamic>{
      		"Content-Type" : "application/json",
      		"Custom-Header" : "Your header"
      	})
        Future<Task> getTasks();
      

    Error Handling

    catchError(Object) should be used for capturing the exception and failed response. You can get the detailed response info from DioError.response.

     client.getTask("2").then((it){
       logger.i(it);
     }).catchError((Object obj) {
        // non-200 error goes here.
        switch (obj.runtimeType) {
          case DioError:
            // Here's the sample to get the failed response error code and message
            final res = (obj as DioError).response;
            logger.e("Got error : ${res.statusCode} -> ${res.statusMessage}");
            break;
          default:
        }
      });
    
    }
    
    1 条回复    2020-03-18 09:24:50 +08:00
    phantomlimb
        1
    phantomlimb  
       2020-03-18 09:24:50 +08:00
    楼主我给你提了好几个 bug,哈哈哈,修的都很快!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2968 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:19 · PVG 08:19 · LAX 17:19 · JFK 20:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.