1 通用库
(1) Entity
/// 新闻分页 responseclass NewsPageListResponseEntity {int? counts;int? pagesize;int? pages;int? page;List<NewsItem>? items;NewsPageListResponseEntity({this.counts,this.pagesize,this.pages,this.page,this.items,});factory NewsPageListResponseEntity.fromJson(Map<String, dynamic> json) =>NewsPageListResponseEntity(counts: json["counts"],pagesize: json["pagesize"],pages: json["pages"],page: json["page"],items:List<NewsItem>.from(json["items"].map((x) => NewsItem.fromJson(x))),);Map<String, dynamic> toJson() => {"counts": counts,"pagesize": pagesize,"pages": pages,"page": page,"items": items != null? List<dynamic>.from(items!.map((x) => x.toJson())): [],};}class NewsItem {String id;String title;String category;String thumbnail;String author;DateTime addtime;String url;NewsItem({required this.id,required this.title,required this.category,required this.thumbnail,required this.author,required this.addtime,required this.url,});factory NewsItem.fromJson(Map<String, dynamic> json) => NewsItem(id: json["id"],title: json["title"],category: json["category"],thumbnail: json["thumbnail"],author: json["author"],addtime: DateTime.parse(json["addtime"]),url: json["url"],);Map<String, dynamic> toJson() => {"id": id,"title": title,"category": category,"thumbnail": thumbnail,"author": author,"addtime": addtime.toIso8601String(),"url": url,};}/// 新闻推荐 requestclass NewsRecommendRequestEntity {String categoryCode;String channelCode;String tag;String keyword;NewsRecommendRequestEntity({required this.categoryCode,required this.channelCode,required this.tag,required this.keyword,});Map<String, dynamic> toJson() => {"categoryCode": categoryCode,"channelCode": channelCode,"tag": tag,"keyword": keyword,};}
(2) BaseProvider
继承自GetConnect
class BaseProvider extends GetConnect {static const SERVER_API_URL = "101.42.134.18:8000";@overridevoid onInit() {httpClient.baseUrl = SERVER_API_URL;// 请求拦截httpClient.addRequestModifier<void>((request) {request.headers['token'] = '12345678';return request;});// 响应拦截httpClient.addResponseModifier((request, response) {return response;});}}
2 法一(最麻烦)
- Provider 提供者模式, 由它决定从哪里、提供什么
- Repository 用来处理拉取数据细节
- Controller 控制器层 只要处理业务就行
(1) Provider
import 'package:fltest/common/utils/base_provider.dart';import 'package:get/get.dart';abstract class INewsProvider {Future<Response<NewsPageListResponseEntity>> getNews();}class NewsProvider extends BaseProvider implements INewsProvider {// 新闻分页// @override// Future<Response<NewsPageListResponseEntity>> getNews() => get("/news");@overrideFuture<Response<NewsPageListResponseEntity>> getNews() async {var response = await get("/news");var data = NewsPageListResponseEntity.fromJson(response.body);return Response(statusCode: response.statusCode,statusText: response.statusText,body: data,);}}
(2) Repository
import 'package:fltest/pages/get_connect/provider.dart';abstract class INewsRepository {Future<NewsPageListResponseEntity> getNews();}class NewsRepository implements INewsRepository {NewsRepository({required this.provider});final INewsProvider provider;@overrideFuture<NewsPageListResponseEntity> getNews() async {final response = await provider.getNews();if (response.status.hasError) {return Future.error(response.statusText!);} else {return response.body!;}}}
(3) Controller
class NewsController extends SuperController<NewsPageListResponseEntity> {NewsController({required this.repository});final INewsRepository repository;@overridevoid onInit() {super.onInit();}// 拉取新闻列表Future<void> getNewsPageList() async {append(() => repository.getNews);}@overridevoid onReady() {print('The build method is done. ''Your controller is ready to call dialogs and snackbars');super.onReady();}@overridevoid onClose() {print('onClose called');super.onClose();}@overridevoid didChangeMetrics() {print('the window size did change');super.didChangeMetrics();}@overridevoid didChangePlatformBrightness() {print('platform change ThemeMode');super.didChangePlatformBrightness();}@overrideFuture<bool> didPushRoute(String route) {print('the route $route will be open');return super.didPushRoute(route);}@overrideFuture<bool> didPopRoute() {print('the current route will be closed');return super.didPopRoute();}@overridevoid onDetached() {print('onDetached called');}@overridevoid onInactive() {print('onInative called');}@overridevoid onPaused() {print('onPaused called');}@overridevoid onResumed() {print('onResumed called');}}
(4) GetView
class NewsView extends GetView<NewsController> {NewsView({Key? key}) : super(key: key);_buildListView(NewsPageListResponseEntity? state) {return ListView.separated(itemCount: state != null ? state.items!.length : 0,itemBuilder: (context, index) {final NewsItem item = state!.items![index];return ListTile(onTap: () => null,title: Text(item.title),trailing: Text("分类 ${item.category}"),);},separatorBuilder: (BuildContext context, int index) {return Divider();},);}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("GetConnect Page"),),body: controller.obx((state) => _buildListView(state),onEmpty: Text("onEmpty"),onLoading: Center(child: Column(children: [Text("没有数据"),ElevatedButton(onPressed: () {controller.getNewsPageList();},child: Text('拉取数据'),),],),),onError: (err) => Text("onEmpty" + err.toString()),),);}}
(5) Bindings
class NewsBinding implements Bindings {@overridevoid dependencies() {Get.lazyPut<INewsProvider>(() => NewsProvider());Get.lazyPut<INewsRepository>(() => NewsRepository(provider: Get.find()));Get.lazyPut(() => NewsController(repository: Get.find()));}}
(6) Route
GetPage(name: AppRoutes.GetConnect,binding: NewsBinding(),page: () => NewsView(),),
3 法二(适中)
使用StateMixin可以节省一些代码, 不用写Repository
(1) provider
import 'package:fltest/common/utils/base_provider.dart';import 'package:get/get.dart';abstract class INewsProvider {Future<Response> getNews();}class NewsStateMixinProvider extends BaseProvider implements INewsProvider {@overrideFuture<Response> getNews() => get("/news");}
(2) controller
class NewsStateMixinController extends GetxControllerwith StateMixin<NewsPageListResponseEntity> {final NewsStateMixinProvider provider;NewsStateMixinController({required this.provider});// 拉取新闻列表Future<void> getNewsPageList() async {// 获取数据final Response response = await provider.getNews();// 判断,如果有错误if (response.hasError) {// 改变数据,传入错误状态,在ui中会处理这些错误change(null, status: RxStatus.error(response.statusText));} else {// 否则,存储数据,改变状态为成功var data = NewsPageListResponseEntity.fromJson(response.body);change(data, status: RxStatus.success());}}}
3 法三(最简单)
(1) http
import 'package:cookie_jar/cookie_jar.dart';import 'package:dio/dio.dart';import 'package:dio_cookie_manager/dio_cookie_manager.dart';const SERVER_API_URL = "101.42.134.18:8000";class HttpUtil {static final HttpUtil _instance = HttpUtil._internal();factory HttpUtil() => _instance;late Dio dio;HttpUtil._internal() {// BaseOptions、Options、RequestOptions 都可以配置参数,优先级别依次递增,且可以根据优先级别覆盖参数BaseOptions options = BaseOptions(// 请求基地址,可以包含子路径baseUrl: SERVER_API_URL,// baseUrl: storage.read(key: STORAGE_KEY_APIURL) ?? SERVICE_API_BASEURL,//连接服务器超时时间,单位是毫秒.connectTimeout: 10000,// 响应流上前后两次接受到数据的间隔,单位为毫秒。receiveTimeout: 5000,// Http请求头.headers: {},// 请求的Content-Type,默认值是"application/json; charset=utf-8".// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,// 可以设置此选项为 `Headers.formUrlEncodedContentType`, 这样[Dio]// 就会自动编码请求体.contentType: 'application/json; charset=utf-8',// [responseType] 表示期望以那种格式(方式)接受响应数据。// 目前 [ResponseType] 接受三种类型 `JSON`, `STREAM`, `PLAIN`.//// 默认值是 `JSON`, 当响应头中content-type为"application/json"时,dio 会自动将响应内容转化为json对象。// 如果想以二进制方式接受响应数据,如下载一个二进制文件,那么可以使用 `STREAM`.//// 如果想以文本(字符串)格式接收响应数据,请使用 `PLAIN`.responseType: ResponseType.json,);dio = Dio(options);// Cookie管理CookieJar cookieJar = CookieJar();dio.interceptors.add(CookieManager(cookieJar));}// restful get 操作Future get(String path, {dynamic queryParameters,Options? options,}) async {var response = await dio.get(path,queryParameters: queryParameters,options: options,);return response.data;}}
(2) api
/// 新闻class NewsAPI {/// 翻页static Future<NewsPageListResponseEntity> newsPageList({NewsRecommendRequestEntity? param}) async {var response = await HttpUtil().get('/news',queryParameters: param?.toJson(),);return NewsPageListResponseEntity.fromJson(response);}}
(3) controller
class NewsDioController extends GetxController {var newsPageList =Rx<NewsPageListResponseEntity>(NewsPageListResponseEntity());@overridevoid onInit() {super.onInit();print("onInit");}@overridevoid onClose() {super.onClose();print("onClose");}getPageList() async {newsPageList.value = await NewsAPI.newsPageList();}}
