小伙伴是否经常打印大一点的json,发现打印log地方,显示不完全 ?很影响调试代码吧;是不是还有其他不满意的地方?! 今天我们就来解决这个问题
首先我们来看一下系统的log输出,测试一下打印一个比较大点的json
Map map = {
"success": true,
"message": "操作成功",
"data": {
"total": 7,
"pageSize": 10,
"pageNo": 1,
"datas": [
{
"id": "5fe143c5b7ab083856e0e71d",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-01 00:00:00"
},
{
"id": "5fe142f3b7ab083856e0e71b",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-02 00:00:00"
},
{
"id": "5fe14297b7ab083856e0e719",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-03 00:00:00"
},
{
"id": "5fe1423db7ab083856e0e717",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-04 00:00:00"
},
{
"id": "5fe141e1b7ab083856e0e715",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-05 00:00:00"
},
{
"id": "5fe13e97b7ab083856e0e713",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-06 00:00:00"
},
{
"id": "5fe13e77b7ab083856e0e711",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-07 00:00:00"
},
{
"id": "5fe143c5b7ab083856e0e71d",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-08 00:00:00"
},
{
"id": "5fe142f3b7ab083856e0e71b",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-09 00:00:00"
},
{
"id": "5fe14297b7ab083856e0e719",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-10 00:00:00"
}
]
}
};
json里面是一个带10个字典的数组--->字典数组;为了方便测试,字典里面的time,对应的值,我调成了不同的日期,方便观看
调用系统的print();
_systemLoggerTestLongText() {
print("$map");
}
打印的结果如下
好啦,我们来diss一下系统的log输出,当前flutter log输出的一些不太方便的地方
第一点, 日志输出时没有带上时间
第二点, 日志输出不支持自定义级别
第三点, 日志输出不支持长文本
...
重点来了,直接上干货,自定义log,完整代码如下
/// DateFormat.
enum DateFormat {
DEFAULT, //yyyy-MM-dd HH:mm:ss.SSS
NORMAL, //yyyy-MM-dd HH:mm:ss
YEAR_MONTH_DAY_HOUR_MINUTE, //yyyy-MM-dd HH:mm
YEAR_MONTH_DAY, //yyyy-MM-dd
YEAR_MONTH, //yyyy-MM
MONTH_DAY, //MM-dd
MONTH_DAY_HOUR_MINUTE, //MM-dd HH:mm
HOUR_MINUTE_SECOND, //HH:mm:ss
HOUR_MINUTE_SECOND_MILLISECOND,//HH时mm分ss秒SSS毫秒
HOUR_MINUTE, //HH:mm
ZH_DEFAULT, //yyyy年MM月dd日 HH时mm分ss秒SSS毫秒
ZH_NORMAL, //yyyy年MM月dd日 HH时mm分ss秒 / timeSeparate: ":" --> yyyy年MM月dd日 HH:mm:ss
ZH_YEAR_MONTH_DAY_HOUR_MINUTE, //yyyy年MM月dd日 HH时mm分 / timeSeparate: ":" --> yyyy年MM月dd日 HH:mm
ZH_YEAR_MONTH_DAY, //yyyy年MM月dd日
ZH_YEAR_MONTH, //yyyy年MM月
ZH_MONTH_DAY, //MM月dd日
ZH_MONTH_DAY_HOUR_MINUTE, //MM月dd日 HH时mm分 / timeSeparate: ":" --> MM月dd日 HH:mm
ZH_HOUR_MINUTE_SECOND, //HH时mm分ss秒
ZH_HOUR_MINUTE, //HH时mm分
}
class ZZLog {
static const String _TAG_DEF = "";
static bool debuggable = false; //是否是debug模式,true: log v 不输出.
static String TAG = _TAG_DEF;
static void init({bool isDebug = false, String tag = _TAG_DEF}) {
debuggable = isDebug;
TAG = tag;
}
static void e(Object object, {String tag}) {
_printLog(tag, ' e=>', object);
}
static void v(Object object, {String tag}) {
if (debuggable) {
_printLog(tag, ' v=>', object);
}
}
static void _printLog(String tag, String stag, Object object) {
String da = object.toString();
String _tag = (tag == null || tag.isEmpty) ? TAG : tag;
while (da.isNotEmpty) {
if (da.length > 512) {
print("${getNowDateStr()}$_tag $stag${da.substring(0, 512)}");
da = da.substring(512, da.length);
} else {
print("${getNowDateStr()}$_tag $stag $da");
da = "";
}
}
}
/// get Now Date Str.(yyyy-MM-dd HH:mm:ss)
static String getNowDateStr() {
return getDateStrByDateTime(DateTime.now());
}
static String getDateStrByDateTime(DateTime dateTime,
{DateFormat format = DateFormat.HOUR_MINUTE_SECOND_MILLISECOND,
String dateSeparate,
String timeSeparate}) {
if (dateTime == null) return null;
String dateStr = dateTime.toString();
dateStr = formatDateTime(dateStr, format, dateSeparate, timeSeparate);
return dateStr;
}
/// format DateTime.
/// time time string.
/// format DateFormat type.
/// dateSeparate date separate.
/// timeSeparate time separate.
static String formatDateTime(String time, DateFormat format,
String dateSeparate, String timeSeparate) {
switch (format) {
case DateFormat.NORMAL: //yyyy-MM-dd HH:mm:ss
time = time.substring(0, "yyyy-MM-dd HH:mm:ss".length);
break;
case DateFormat.YEAR_MONTH_DAY_HOUR_MINUTE: //yyyy-MM-dd HH:mm
time = time.substring(0, "yyyy-MM-dd HH:mm".length);
break;
case DateFormat.YEAR_MONTH_DAY: //yyyy-MM-dd
time = time.substring(0, "yyyy-MM-dd".length);
break;
case DateFormat.YEAR_MONTH: //yyyy-MM
time = time.substring(0, "yyyy-MM".length);
break;
case DateFormat.MONTH_DAY: //MM-dd
time = time.substring("yyyy-".length, "yyyy-MM-dd".length);
break;
case DateFormat.MONTH_DAY_HOUR_MINUTE: //MM-dd HH:mm
time = time.substring("yyyy-".length, "yyyy-MM-dd HH:mm".length);
break;
case DateFormat.HOUR_MINUTE_SECOND: //HH:mm:ss
time =
time.substring("yyyy-MM-dd ".length, "yyyy-MM-dd HH:mm:ss".length);
break;
case DateFormat.HOUR_MINUTE: //HH:mm
time = time.substring("yyyy-MM-dd ".length, "yyyy-MM-dd HH:mm".length);
break;
default:
break;
}
time = dateTimeSeparate(time, dateSeparate, timeSeparate);
return time;
}
/// date Time Separate.
static String dateTimeSeparate(
String time, String dateSeparate, String timeSeparate) {
if (dateSeparate != null) {
time = time.replaceAll("-", dateSeparate);
}
if (timeSeparate != null) {
time = time.replaceAll(":", timeSeparate);
}
return time;
}
}
#####Round 1
现在来调用我们封装好的log工具来输出上面长文本,结果如下:
_myLoggerTestLongText() {
ZZLog.e("$map");
}
大家看一下,自定义的log,是不是把10个字典都打印出来了!!! 此时应该有掌声.
Round 2
我们再来测试一下,正常的文本输出,测试代码及结果如下图
_myLoggerTestShortTextTagV() {
ZZLog.v("v object 1 ");
ZZLog.v("v object 2 ");
ZZLog.v("v object 3 ");
ZZLog.v("v object 4 ");
}
_myLoggerTestShortTextTagE() {
ZZLog.e("e object 1 ");
ZZLog.e("e object 2 ");
ZZLog.e("e object 3 ");
ZZLog.e("e object 4 ");
}
补充一下,还有些小技巧
**自定义的log还可以 定义在生产环境,与开发环境,可以自由切换
**自定义的log,如果你觉得上面本人的打印格式你不满意,还可以自己去简单改一下代码,就可以生成你满意的格式,
测试的完整代码如下:
import 'package:flutter/material.dart';
import 'package:flutter_app_log_test/zz_log.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_myLoggerTestShortTextTagE();
_myLoggerTestShortTextTagV();
},
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
Map map = {
"success": true,
"message": "操作成功",
"data": {
"total": 7,
"pageSize": 10,
"pageNo": 1,
"datas": [
{
"id": "5fe143c5b7ab083856e0e71d",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-01 00:00:00"
},
{
"id": "5fe142f3b7ab083856e0e71b",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-02 00:00:00"
},
{
"id": "5fe14297b7ab083856e0e719",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-03 00:00:00"
},
{
"id": "5fe1423db7ab083856e0e717",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-04 00:00:00"
},
{
"id": "5fe141e1b7ab083856e0e715",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-05 00:00:00"
},
{
"id": "5fe13e97b7ab083856e0e713",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-06 00:00:00"
},
{
"id": "5fe13e77b7ab083856e0e711",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-07 00:00:00"
},
{
"id": "5fe143c5b7ab083856e0e71d",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-08 00:00:00"
},
{
"id": "5fe142f3b7ab083856e0e71b",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-09 00:00:00"
},
{
"id": "5fe14297b7ab083856e0e719",
"devName": "Sensor-2E9599",
"roomName": null,
"statusName": "触发报警",
"time": "2020-12-10 00:00:00"
}
]
}
};
_myLoggerTestShortTextTagV() {
ZZLog.v("v object 1 ");
ZZLog.v("v object 2 ");
ZZLog.v("v object 3 ");
ZZLog.v("v object 4 ");
}
_myLoggerTestShortTextTagE() {
ZZLog.e("e object 1 ");
ZZLog.e("e object 2 ");
ZZLog.e("e object 3 ");
ZZLog.e("e object 4 ");
}
_myLoggerTestLongText() {
ZZLog.e("$map");
}
_systemLoggerTestLongText() {
print("$map");
}
}
结尾
今天的分享先到这里了,后续会分享更多的干货,欢迎点赞,评论,加关注啦,祝君好运!!