0

さまざまな応答セットに対して json-annotation を使用して、さまざまな .g.dart クラスを作成しています。現在、リクエストを作成し、レスポンスをモデル クラスにマッピングするために Chopper Client を使用しているときは、コンバーターを作成しています。ただし、チョッパー クライアントに割り当てることができるコンバータは 1 つだけです。私が達成しようとしているのは、get_it パッケージを使用してチョッパー クライアントを初期化することです。異なるリクエストを行う際に、異なるコンバーターをチョッパークライアントに割り当てるにはどうすればよいですか。 これは、クラスの初期化に get_it パッケージが使用される基本クラスです。

base.dart

import 'package:chopper/chopper.dart' as chopper;

chopper.ChopperClient getBaseChopperClient(GetIt c) {
  return chopper.ChopperClient(
    baseUrl: 'https://',
    interceptors: [chopper.HttpLoggingInterceptor()],
    converter: HomeModelConverter(),
    errorConverter: chopper.JsonConverter(),
  );
}

c.registerLazySingleton(() {
  var chopper = getBaseChopperClient(c);
  return chopper;
});

c.registerFactory(() => HomeApiService.create(c<chopper.ChopperClient>()));

この ChopperService クラスから Get リクエストを作成し、HomeModelConverter を使用して応答を HomeModelResponse にマッピングします。この HomeModelConverter は、上記のチョッパー クライアント オブジェクトに割り当てられます。

home_api_service.dart

part 'home_api.chopper.dart';

@ChopperApi(baseUrl: '')
abstract class HomeApiService extends ChopperService {
  @Get(path: '')
  Future<Response<HomeModelResponse>> getData();

  static HomeApiService create([ChopperClient? client]) =>
      _$HomeApiService(client);
}

これは、HomeModelResponse 固有のコンバーター クラスです。decodeJson 関数内では、HomeModelResponse にデコードすることを明示的に言及しています。

home_model_converter.dart

class HomeModelConverter implements Converter {
  @override
  Request convertRequest(Request request) {
    final req = applyHeader(
      request,
      contentTypeKey,
      jsonHeaders,
      override: false,
    );

    return encodeJson(req);
  }

  Request encodeJson(Request request) {
    var contentType = request.headers[contentTypeKey];
    if (contentType != null && contentType.contains(jsonHeaders)) {
      return request.copyWith(body: json.encode(request.body));
    }
    return request;
  }

  Response<BodyType> decodeJson<BodyType, InnerType>(Response response) {
    var contentType = response.headers[contentTypeKey];
    var body = response.body;
    if (contentType != null && contentType.contains(jsonHeaders)) {
      body = utf8.decode(response.bodyBytes);
    }
    try {
      var mapData = json.decode(body);
      var popular = HomeModelResponse.fromJson(mapData);
      return response.copyWith<BodyType>(body: popular as BodyType);
    } catch (e) {
      chopperLogger.warning(e);
      return response.copyWith<BodyType>(body: body);
    }
  }

  @override
  Response<BodyType> convertResponse<BodyType, InnerType>(Response response) {
    return decodeJson<BodyType, InnerType>(response);
  }
}

これは、受信応答が自動的にマップされる HomeModelResponse です。

home_model_response.dart

part 'home_model_response.g.dart';

@JsonSerializable()
class HomeModelResponse {
  ------------
-----------
  HomeModelResponse({
    ---------
    ---------
  });
  factory HomeModelResponse.fromJson(Map<String, dynamic> json) =>
      _$HomeModelResponseFromJson(json);
  Map<String, dynamic> toJson() => _$HomeModelResponseToJson(this);
}

上記のコードは home_api_service に対して正常に機能しており、適切な応答が得られています。 ここで、AddApiService などの別のサービスを作成したいと考えています。これには別のコンバーターがあります。チョッパー クライアントでコンバーターを動的に変更する方法。現在、HomeModelConverter は初期化時にハードコーディングされて割り当てられています。すべてのコンバーターに対して複数の ChopperClient を作成したくありません。ここで立ち往生。または、汎用コンバーターを作成するオプション

このアプローチが問題ないかどうか、またはフラッターに従うためのより良いアプローチがあるかどうかを誰かが提案できる場合。

4

1 に答える 1

0

自分で試して、少し回避策を実行しました。現在、私の要件に従って動作しています。

HomeApiService の初期化を次のように変更しました。

c.registerFactory(() => HomeModelConverter());

c.registerFactory(() => HomeApiService.create(
    getBaseChopperClient(c, c<HomeModelConverter>())));

以下のようにチョッパークライアントの初期化を変更しました。ここでの唯一の欠点は、新しい Chopper Service ごとに、Chopper クライアントの新しいオブジェクトが作成されることです。

chopper.ChopperClient getBaseChopperClient(
  GetIt c, chopper.Converter converter) {
return chopper.ChopperClient(
  baseUrl: '', // provide your own base url
  interceptors: [chopper.HttpLoggingInterceptor()],
  converter: converter,
  errorConverter: chopper.JsonConverter(),
);

}

于 2021-04-11T05:46:22.100 に答える