library_architecture_mvvm_modify 6.1.2 copy "library_architecture_mvvm_modify: ^6.1.2" to clipboard
library_architecture_mvvm_modify: ^6.1.2 copied to clipboard

MVVM Modify for Dart but you can also port to another language

example/lib/main.dart

import 'dart:convert';
import 'package:library_architecture_mvvm_modify/library_architecture_mvvm_modify.dart';
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';

@immutable
final class FactoryModelWrapperRepositoryUtility {
  const FactoryModelWrapperRepositoryUtility._();

  static IPAddressWrapperRepository
      getIPAddressWrapperRepositoryFromNamedHttpClientService(
          BaseNamedHttpClientService namedHttpClientService) {
    return IPAddressWrapperRepository(namedHttpClientService);
  }
}

@immutable
final class KeysUrlEndpointUtility {
  /* JsonipAPI */
  static const String jsonipAPI = "https://jsonip.com";
  static const String jsonipAPIQQProviders = "$jsonipAPI/providers";

  const KeysUrlEndpointUtility._();
}

@immutable
final class ReadyDataUtility {
  static const String unknown = "unknown";
  static const String success = "success";

  const ReadyDataUtility._();
}

@immutable
final class KeysHttpClientServiceUtility {
  /* IPAddress */
  static const String iPAddressQQIp = "ip";

  const KeysHttpClientServiceUtility._();
}

@immutable
base class IPAddress extends BaseModel {
  final String ip;

  const IPAddress(this.ip) : super(ip);

  @override
  IPAddress clone() => IPAddress(ip);

  @override
  String toString() {
    return "IPAddress(ip: $ip)";
  }
}

@immutable
base class ListIPAddress<T extends IPAddress> extends BaseListModel<T> {
  const ListIPAddress(super.listModel) : super();

  @override
  ListIPAddress<T> clone() {
    List<T> newListModel = List.empty(growable: true);
    for (final T model in listModel) {
      newListModel.add(model.clone() as T);
    }
    return ListIPAddress<T>(newListModel);
  }

  @override
  String toString() {
    String strListModel = "\n";
    for (final T itemModel in listModel) {
      strListModel += "$itemModel,\n";
    }
    return "ListIPAddress(listModel: [$strListModel])";
  }
}

@immutable
base class IPAddressWrapper extends BaseModelWrapper {
  const IPAddressWrapper(super.listObject);

  @override
  IPAddress createModel() {
    return IPAddress(listObject[0]);
  }
}

@immutable
base class ListIPAddressWrapper extends BaseListModelWrapper {
  const ListIPAddressWrapper(super.listsListObject);

  @override
  ListIPAddress createListModel() {
    final List<IPAddress> listModel = List.empty(growable: true);
    for (final List<dynamic> itemListObject in listsListObject) {
      final iPAddressWrapper = IPAddressWrapper(itemListObject);
      listModel.add(iPAddressWrapper.createModel());
    }
    return ListIPAddress(listModel);
  }
}

abstract class BaseNamedHttpClient {
  const BaseNamedHttpClient();

  Future<http.Response> get(Uri url, {Map<String, String>? headers});

  Future<http.Response> post(Uri url,
      {Map<String, String>? headers, body, Encoding? encoding});

  Future<void> close();
}

final class DefaultHttpClient extends BaseNamedHttpClient {
  final http.Client _client;

  const DefaultHttpClient(this._client);

  @override
  Future<http.Response> get(Uri url, {Map<String, String>? headers}) {
    return _client.get(url, headers: headers);
  }

  @override
  Future<http.Response> post(Uri url,
      {Map<String, String>? headers, Object? body, Encoding? encoding}) {
    return _client.post(url, headers: headers, body: body, encoding: encoding);
  }

  @override
  Future<void> close() async {
    _client.close();
  }
}

final class TimeoutHttpClient extends BaseNamedHttpClient {
  final http.Client _client;
  final Duration _timeout;

  const TimeoutHttpClient(this._client, this._timeout);

  @override
  Future<http.Response> get(Uri url, {Map<String, String>? headers}) {
    return _client.get(url, headers: headers).timeout(_timeout);
  }

  @override
  Future<http.Response> post(Uri url,
      {Map<String, String>? headers, Object? body, Encoding? encoding}) {
    return _client
        .post(url, headers: headers, body: body, encoding: encoding)
        .timeout(_timeout);
  }

  @override
  Future<void> close() async {
    _client.close();
  }
}

abstract class BaseNamedHttpClientService {
  const BaseNamedHttpClientService();

  BaseNamedHttpClient? get getParameterNamedHttpClient;
}

final class DefaultHttpClientService extends BaseNamedHttpClientService {
  static final DefaultHttpClientService instance = DefaultHttpClientService._();
  BaseNamedHttpClient? _namedHttpClient;

  DefaultHttpClientService._();

  @override
  BaseNamedHttpClient? get getParameterNamedHttpClient {
    if (_namedHttpClient != null) {
      return _namedHttpClient;
    }
    _namedHttpClient = DefaultHttpClient(http.Client());
    return _namedHttpClient;
  }
}

final class TimeoutHttpClientService extends BaseNamedHttpClientService {
  static final TimeoutHttpClientService instance = TimeoutHttpClientService._();
  BaseNamedHttpClient? _namedHttpClient;

  TimeoutHttpClientService._();

  @override
  BaseNamedHttpClient? get getParameterNamedHttpClient {
    if (_namedHttpClient != null) {
      return _namedHttpClient;
    }
    _namedHttpClient =
        TimeoutHttpClient(http.Client(), const Duration(seconds: 5));
    return _namedHttpClient;
  }
}

@immutable
base class IPAddressWrapperRepository<T extends IPAddressWrapper,
    Y extends ListIPAddressWrapper> extends BaseModelWrapperRepository {
  @protected
  final BaseNamedHttpClientService namedHttpClientService;

  const IPAddressWrapperRepository(this.namedHttpClientService);

  @override
  void dispose() {}

  Future<ResultWithModelWrapper<T>>
      getIPAddressParameterNamedHttpClientService() async {
    try {
      final response = await namedHttpClientService.getParameterNamedHttpClient
          ?.get(Uri.parse(KeysUrlEndpointUtility.jsonipAPI));
      if (response?.statusCode != 200) {
        throw NetworkException.fromKeyAndStatusCode(this,
            response?.statusCode.toString() ?? "", response?.statusCode ?? 0);
      }
      final Map<String, dynamic> data = jsonDecode(response?.body ?? "");
      final ipByIPAddress = getSafeValueFromMapAndKeyAndDefaultValue(
          data, KeysHttpClientServiceUtility.iPAddressQQIp, "");
      return ResultWithModelWrapper.success(
          IPAddressWrapper([ipByIPAddress]) as T);
    } on NetworkException catch (e) {
      return ResultWithModelWrapper.exception(e);
    } catch (e) {
      return ResultWithModelWrapper.exception(LocalException(
          this, EnumGuilty.device, ReadyDataUtility.unknown, e.toString()));
    }
  }
}

enum EnumDataForMainVM { isLoading, exception, success }

final class DataForMainVM extends BaseDataForNamed<EnumDataForMainVM> {
  IPAddress iPAddress;

  DataForMainVM(super.isLoading, this.iPAddress);

  @override
  EnumDataForMainVM get getEnumDataForNamed {
    if (isLoading) {
      return EnumDataForMainVM.isLoading;
    }
    if (exceptionController.isWhereNotEqualsNullParameterException()) {
      return EnumDataForMainVM.exception;
    }
    return EnumDataForMainVM.success;
  }

  @override
  String toString() {
    return "DataForMainVM(isLoading: $isLoading, "
        "exceptionController: $exceptionController, "
        "iPAddress: $iPAddress)";
  }
}

final class MainVM {
  // ModelWrapperRepository
  final _iPAddressWrapperRepository = FactoryModelWrapperRepositoryUtility
      .getIPAddressWrapperRepositoryFromNamedHttpClientService(
          TimeoutHttpClientService.instance);

  // TempCacheProvider
  final _tempCacheProvider = TempCacheProvider();

  // NamedUtility

  // NamedStreamWState
  late final BaseNamedStreamWState<DataForMainVM> _namedStreamWState;

  MainVM() {
    _namedStreamWState = DefaultStreamWState<DataForMainVM>(
        DataForMainVM(true, const IPAddress("")));
  }

  Future<void> init() async {
    _namedStreamWState.listenStreamDataForNamedFromCallback((event) {
      _build();
    });
    final firstRequest = await _firstRequest();
    debugPrint("MainVM: $firstRequest");
    _namedStreamWState.notifyStreamDataForNamed();
  }

  void dispose() {
    _iPAddressWrapperRepository.dispose();
    _tempCacheProvider.dispose([]);
    _namedStreamWState.dispose();
  }

  void _build() {
    final dataWNamed = _namedStreamWState.getDataForNamed;
    switch (dataWNamed.getEnumDataForNamed) {
      case EnumDataForMainVM.isLoading:
        debugPrint("Build: IsLoading");
        break;
      case EnumDataForMainVM.exception:
        debugPrint(
            "Build: Exception(${dataWNamed.exceptionController.getKeyParameterException})");
        break;
      case EnumDataForMainVM.success:
        debugPrint("Build: Success(${dataWNamed.iPAddress})");
        break;
    }
  }

  Future<String> _firstRequest() async {
    final getIPAddressParameterNamedHttpClientService =
        await _iPAddressWrapperRepository
            .getIPAddressParameterNamedHttpClientService();
    if (getIPAddressParameterNamedHttpClientService.exceptionController
        .isWhereNotEqualsNullParameterException()) {
      return _firstQQFirstRequestQQGetIPAddressParameterNamedHttpClientService(
          getIPAddressParameterNamedHttpClientService.exceptionController);
    }
    _namedStreamWState.getDataForNamed.isLoading = false;
    _namedStreamWState.getDataForNamed.iPAddress =
        getIPAddressParameterNamedHttpClientService.modelWrapper!.createModel();
    return ReadyDataUtility.success;
  }

  Future<String>
      _firstQQFirstRequestQQGetIPAddressParameterNamedHttpClientService(
          ExceptionController exceptionController) async {
    _namedStreamWState.getDataForNamed.isLoading = false;
    _namedStreamWState.getDataForNamed.exceptionController =
        exceptionController;
    return exceptionController.getKeyParameterException;
  }
}

Future<void> main() async {
  final mainVM = MainVM();
  await mainVM.init();
  mainVM.dispose();
}
// EXPECTED OUTPUT:
//
// MainVM: success
// Build: Success(IPAddress(ip: ${your_ip}))
//
// Process finished with exit code 0

/// OR

// EXPECTED OUTPUT:
//
// ===start_to_trace_exception===
//
// WhereHappenedException(Class) --> ${WhereHappenedException(Class)}
// NameException(Class) --> ${NameException(Class)}
// toString() --> ${toString()}
//
// ===end_to_trace_exception===
//
// MainVM: ${getKeyParameterException}
// Build: Exception(${getKeyParameterException})
//
// Process finished with exit code 0
1
likes
150
points
204
downloads

Publisher

unverified uploader

Weekly Downloads

MVVM Modify for Dart but you can also port to another language

Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

ansicolor, meta

More

Packages that depend on library_architecture_mvvm_modify