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
140
points
127
downloads

Publisher

unverified uploader

Weekly Downloads

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

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

ansicolor, meta

More

Packages that depend on library_architecture_mvvm_modify