完成Iconfont、应用页、网络缓存以及代理

This commit is contained in:
胡天 2023-07-20 18:24:10 +08:00
parent 756108fb8d
commit c47b5207de
13 changed files with 461 additions and 5 deletions

9
lib/config/proxy.dart Normal file
View File

@ -0,0 +1,9 @@
//
const ProxyEnable = false;
/// IP
// const PROXY_IP = '192.168.1.105';
const ProxyIP = '172.16.43.74';
///
const ProxyPort = 8866;

View File

@ -13,7 +13,10 @@ class Global {
WidgetsFlutterBinding.ensureInitialized();
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
// UI
setSystemUi();
// easyLoading
Loading();
await Get.putAsync<StorageService>(() => StorageService().init());
@ -24,6 +27,7 @@ class Global {
static void setSystemUi() {
if (GetPlatform.isAndroid) {
// android
SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarBrightness: Brightness.light,

View File

@ -0,0 +1,10 @@
import 'package:get/get.dart';
import 'application_controller.dart';
class ApplicationBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => ApplicationController());
}
}

View File

@ -0,0 +1,115 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:news_getx/theme/app_colors.dart';
import 'package:news_getx/utils/iconfont.dart';
class ApplicationController extends GetxController {
///
// tab
final _page = 0.obs;
set page(value) => _page.value = value;
get page => _page.value;
///
///
// tab
late final List<String> tabTitles;
//
late final PageController pageController;
//
late final List<BottomNavigationBarItem> bottomTabs;
///
// tab栏动画
void handleNavBarTap(int page) {
pageController.animateToPage(
page,
duration: const Duration(seconds: 1),
curve: Curves.ease,
);
}
// tab栏页码切换
void handlePageChange(int newPage) {
page = newPage;
}
/// scheme TODO uriLink
bool isInitialUriIsHandled = false;
StreamSubscription? uriSub;
///
@override
void onInit() {
super.onInit();
// tab
tabTitles = ['Welcome', 'Cagegory', 'Bookmarks', 'Account'];
bottomTabs = <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Iconfont.home,
color: AppColors.tabBarElement,
),
activeIcon: Icon(
Iconfont.home,
color: AppColors.secondaryElementText,
),
label: "main",
backgroundColor: AppColors.primaryBackground,
),
BottomNavigationBarItem(
icon: Icon(
Iconfont.grid,
color: AppColors.tabBarElement,
),
activeIcon: Icon(
Iconfont.grid,
color: AppColors.secondaryElementText,
),
label: 'category',
backgroundColor: AppColors.primaryBackground,
),
BottomNavigationBarItem(
icon: Icon(
Iconfont.tag,
color: AppColors.tabBarElement,
),
activeIcon: Icon(
Iconfont.tag,
color: AppColors.secondaryElementText,
),
label: 'tag',
backgroundColor: AppColors.primaryBackground,
),
BottomNavigationBarItem(
icon: Icon(
Iconfont.me,
color: AppColors.tabBarElement,
),
activeIcon: Icon(
Iconfont.me,
color: AppColors.secondaryElementText,
),
label: 'my',
backgroundColor: AppColors.primaryBackground,
),
];
pageController = PageController(initialPage: page);
}
@override
void dispose() {
uriSub?.cancel();
pageController.dispose();
super.dispose();
}
}

View File

@ -0,0 +1,74 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:news_getx/modules/widgets/app_bar.dart';
import 'package:news_getx/theme/app_colors.dart';
import 'application_controller.dart';
class ApplicationPage extends GetView<ApplicationController> {
const ApplicationPage({Key? key}) : super(key: key);
AppBar _buildAppBar() {
return transparentAppBar(
title: Obx(
() => Text(
controller.tabTitles[controller.page],
style: TextStyle(
color: AppColors.primaryText,
fontFamily: "Montserrat",
fontSize: 18.sp,
fontWeight: FontWeight.w600,
),
),
),
actions: <Widget>[
IconButton(
onPressed: () {},
icon: Icon(
Icons.search,
color: AppColors.primaryText,
),
)
],
);
}
Widget _buildPageView() {
return PageView(
//
physics: NeverScrollableScrollPhysics(),
controller: controller.pageController,
onPageChanged: controller.handlePageChange,
children: <Widget>[
Text('Main'),
Text('Category'),
Text('BookmarksPage'),
Text('AccountPage'),
],
);
}
Widget _buildBottomNavigationBar() {
return Obx(
() => BottomNavigationBar(
items: controller.bottomTabs,
currentIndex: controller.page,
//
type: BottomNavigationBarType.fixed,
onTap: controller.handleNavBarTap,
showSelectedLabels: false,
showUnselectedLabels: false,
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildAppBar(),
body: _buildPageView(),
bottomNavigationBar: _buildBottomNavigationBar(),
);
}
}

View File

@ -0,0 +1,10 @@
import 'package:get/get.dart';
import 'main_controller.dart';
class MainBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => MainController());
}
}

View File

@ -0,0 +1,5 @@
import 'package:get/get.dart';
class MainController extends GetxController {
}

View File

@ -0,0 +1,15 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'main_controller.dart';
class MainPage extends StatelessWidget {
const MainPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final controller = Get.find<MainController>();
return Container();
}
}

View File

@ -10,11 +10,8 @@ AppBar transparentAppBar({
return AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
title: title != null
? Center(
child: title,
)
: null,
centerTitle: true,
title: title,
leading: leading,
actions: actions,
);

View File

@ -1,4 +1,6 @@
import 'package:get/get.dart';
import 'package:news_getx/modules/application/application_binding.dart';
import 'package:news_getx/modules/application/application_page.dart';
import 'package:news_getx/modules/not_found/not_found_binding.dart';
import 'package:news_getx/modules/not_found/not_found_page.dart';
import 'package:news_getx/modules/sign_in/sign_in_binding.dart';
@ -33,5 +35,11 @@ abstract class AppPages {
page: () => NotFoundPage(),
binding: NotFoundBinding(),
),
//
GetPage(
name: AppRoutes.Application,
page: () => ApplicationPage(),
binding: ApplicationBinding(),
),
];
}

View File

@ -1,12 +1,18 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:get/get.dart' hide FormData;
import 'package:news_getx/config/cache.dart';
import 'package:news_getx/config/proxy.dart';
import 'package:news_getx/config/server.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:news_getx/data/services/config.dart';
import 'package:news_getx/data/services/user.dart';
import 'package:news_getx/utils/loading.dart';
import 'package:news_getx/utils/net_cache.dart';
/*
* http
@ -56,10 +62,29 @@ class HttpUtil {
dio = Dio(options);
//
if (!ConfigService.to.isRelease && ProxyEnable) {
dio.httpClientAdapter = IOHttpClientAdapter(
createHttpClient: () {
final client = HttpClient();
client.findProxy = (uri) {
return "PROXY $ProxyIP:$ProxyPort";
};
//
client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
return client;
}
);
}
// Cookie管理
CookieJar cookieJar = CookieJar();
// CookieManager
dio.interceptors.add(CookieManager(cookieJar));
//
if (CacheEnable) {
dio.interceptors.add(NetCache());
}
//
dio.interceptors.add(InterceptorsWrapper(

94
lib/utils/iconfont.dart Normal file
View File

@ -0,0 +1,94 @@
import 'package:flutter/material.dart';
class Iconfont {
// iconName: share
static const share = IconData(
0xe60d,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: fav
static const fav = IconData(
0xe60c,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-linkedin
static const sociallinkedin = IconData(
0xe605,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-apple
static const socialapple = IconData(
0xe606,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-octocat
static const socialoctocat = IconData(
0xe607,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-reddit
static const socialreddit = IconData(
0xe608,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-snapchat
static const socialsnapchat = IconData(
0xe609,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-skype
static const socialskype = IconData(
0xe60a,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-twitter
static const socialtwitter = IconData(
0xe60b,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: me
static const me = IconData(
0xe604,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: tag
static const tag = IconData(
0xe603,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: grid
static const grid = IconData(
0xe602,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: home
static const home = IconData(
0xe601,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
}

90
lib/utils/net_cache.dart Normal file
View File

@ -0,0 +1,90 @@
import 'dart:collection';
import 'package:dio/dio.dart';
import 'package:news_getx/config/cache.dart';
class CacheObject {
Response response;
int timestamp;
CacheObject(this.response)
: timestamp = DateTime.now().millisecondsSinceEpoch;
@override
bool operator ==(Object other) {
return response.hashCode == other.hashCode;
}
@override
int get hashCode => response.realUri.hashCode;
}
class NetCache extends Interceptor {
// 使LinkedHashMap, {}
var cache = <String, CacheObject>{};
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
// refresh标记是否是"下拉刷新"
bool refresh = options.extra['refresh'] == true;
if (refresh) {
//
if (options.extra['list']) {
//url中包含当前path的缓存全部删除
cache.removeWhere((key, value) => key.contains(options.path));
} else {
cacheDelete(options.uri.toString());
}
}
// get
if (options.extra['noCache'] != true &&
options.method.toLowerCase() == "get") {
String key = options.extra['cacheKey'] ?? options.uri.toString();
var ob = cache[key];
if (ob != null) {
//
if ((DateTime.now().millisecondsSinceEpoch - ob.timestamp) / 1000 <
CacheMaxAge) {
CacheObject? cacheRes = cache[key];
if (cacheRes != null) {
handler.resolve(cacheRes.response);
return;
}
} else {
//
cacheDelete(key);
}
}
}
super.onRequest(options, handler);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
//
_setCache(response);
super.onResponse(response, handler);
}
_setCache(Response response) {
RequestOptions options = response.requestOptions;
// get
if (options.extra["noCache"] != true &&
options.method.toLowerCase() == "get") {
//
if (cache.length >= CacheMaxCount) {
cacheDelete(cache.keys.first);
}
String key = options.extra['cacheKey'] ?? options.uri.toString();
cache[key] = CacheObject(response);
}
}
void cacheDelete(String key) {
cache.remove(key);
}
}