Flutter项目从0开始

flutter项目重构,趁此机会整理一下所用到的知识

应用的初步构建

Android名称和图标修改

/android/app/src/main/AndroidManifest.xml中修改相应配置

<application
    android:name="io.flutter.app.FlutterApplication"
    android:label="cloudrecord"
    android:icon="@mipmap/ic_launcher">

label为应用名称,icon为图标。@mipmap代表/android/app/src/main/res/中的mipmap文件夹,图像需要png格式。

iOS名称和图标修改

/ios/Runner/info.plist中修改名称

<key>CFBundlePackageType</key>
<string>APPL</string>

\ios\Runner\Assets.xcassets\AppIcon.appiconset文件夹中修改图标,在\ios\Runner\Assets.xcassets\AppIcon.appiconset\Contents.json中修改对应关系

##修改应用版本号
pubspec.yaml中可看到版本号为version: 1.0.0+1
在Android中,应用的版本分为versionCode & versionName
versionCode:内部管理的版本号
versionName:用户显示的版本号
在iOS中,应用的版本分为 version & build
version:用户显示的版本
build:内部管理的版本
Flutter中对应的版本号为
1.0.0:用户显示的版本
1:内部管理的版本

##用户权限配置
/android/app/src/main/AndroidManifest.xml中修改权限配置
加入以下两行
在这里插入图片描述

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

分别为存储空间以及网络请求

网络封装

获取Dio依赖

flutter自带网络请求库功能较弱且配置麻烦,因此使用dio库作为http请求的包
pubspec.yaml中的dependencies下配置相应依赖包
这里我一次加入后面需要的大多数包,注意版本匹配
在这里插入图片描述

然后点击peckages get获取相应的包

为网络传输添加弹窗提示

在进行体积较大数据的传输时,如果没有提示,用户会感到迷惑,所以做一个半透明的loading窗口

使用dialog方法

import 'package:flutter/material.dart';

dialog方法详解
Future<T> showDialog<T>({
        BuildContext context,
        bool barrierDismissible, 
        Widget child,
        Widget Function(BuildContext) builder,
        bool useRootNavigator,
        RouteSettings routeSettings
    }) 

其中 contextbuilder 是必传项,builder 需要返回一个 Widget,这个 Widget 会被作为 dialog 展示在页面上

编写一个半透明窗口作为showDialog的widget

class NetLoadingDialog extends StatefulWidget {
String loadingText;
NetLoadingDialog(
    {Key key,
        this.loadingText = "loading...",
    })
    : super(key: key);

@override
State<NetLoadingDialog> createState() => _LoadingDialog();
}

class _LoadingDialog extends State<NetLoadingDialog> {

@override
void initState() {
    super.initState();
}

@override
Widget build(BuildContext context) {
    return new GestureDetector(
//      点击退出当前页面
//      onTap: (){Navigator.of(context).pop();},
    child: Material(
        type: MaterialType.transparency,
        child: new Center(
        child: new SizedBox(
            width: 120.0,
            height: 120.0,
            child: new Container(
            decoration: ShapeDecoration(
                color: Color(0xffffffff),
                shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(
                    Radius.circular(8.0),
                ),
                ),
            ),
            child: new Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                new CircularProgressIndicator(),
                new Padding(
                    padding: EdgeInsets.only(
                    top: 20.0,
                    ),
                    child: new Text(
                    widget.loadingText,
                    style: new TextStyle(fontSize: 12.0),
                    ),
                ),
                ],
            ),
            ),
        ),
        ),
    ),
    );
}
}

效果如下
在这里插入图片描述

窗口使用了覆盖屏幕的组件

//会在当前屏幕内容基础上再覆盖一个满屏的区域
Material(
	type = MaterialType.transparency, //屏幕灰色透明,即相当于覆盖一个灰色透明的div
	child:内容组件
	
)

动画使用了进度条组件,包含两种,圆形进度条CircularProgressIndicator和条形进度条LinearProgressIndicator

new LinearProgressIndicator(
    backgroundColor: Colors.blue,
    value: 0.2, //如果 value 为 null 或空,则显示一个动画,否则显示一个定值。Progress 的值只能设置 0 ~ 1.0,如果大于 1,则表示已经结束。
    valueColor: new AlwaysStoppedAnimation<Color>(Colors.red),
),

new CircularProgressIndicator(
    strokeWidth: 4.0,
    backgroundColor: Colors.blue,
    value: 0.2,
    valueColor: new AlwaysStoppedAnimation<Color>(Colors.red),
),  

对Dio进行封装

参考博客https://www.jianshu.com/p/edb5bae85732
非常感谢!

import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'showAlertDialogClass.dart';
import 'dart:async';
import 'package:dio/dio.dart';
import 'dart:convert';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'globalConfig.dart';
import 'resultCode.dart';

/*
* 网络请求管理类
*/
class DioManager {
//写一个单例
//在 Dart 里,带下划线开头的变量是私有变量
static DioManager _instance;

static DioManager getInstance() {
    if (_instance == null) {
    _instance = DioManager();
    }
    return _instance;
}

Dio dio = new Dio();
DioManager() {
    // Set default configs
    dio.options.headers = {
    "version": '2.0.9',
    };
    dio.options.baseUrl = " ";
    dio.options.connectTimeout = 5000;
    dio.options.receiveTimeout = 3000;

    dio.interceptors
        .add(LogInterceptor(responseBody: GlobalConfig.isDebug)); //是否开启请求日志
    dio.interceptors.add(CookieManager(CookieJar())); //缓存相关类
}

//get请求
get(String url, Map params, Function successCallBack,
    Function errorCallBack) async {
    _requstHttp(url, successCallBack, 'get', params, errorCallBack);
}

//post请求
post(String url, params, Function successCallBack,
    Function errorCallBack) async {
    _requstHttp(url, successCallBack, "post", params, errorCallBack);
}

_requstHttp(String url, Function successCallBack,
    [String method, params, Function errorCallBack]) async {
    Response response;
    try {
    if (method == 'get') {
        if (params != null && params.length > 0) {
        response = await dio.get(url, queryParameters: params);
        } else {
        response = await dio.get(url);
        }
    } else if (method == 'post') {
        if (params != null && params.length > 0) {
        response = await dio.post(url, data: params);
        } else {
        response = await dio.post(url);
        }
    }
    } on DioError catch (error) {
    // 请求错误处理
    Response errorResponse;
    if (error.response != null) {
        errorResponse = error.response;
    } else {
        errorResponse = new Response(statusCode: 666);
    }
    // 请求超时
    if (error.type == DioErrorType.CONNECT_TIMEOUT) {
        errorResponse.statusCode = ResultCode.CONNECT_TIMEOUT;
    }
    // 一般服务器错误
    else if (error.type == DioErrorType.RECEIVE_TIMEOUT) {
        errorResponse.statusCode = ResultCode.RECEIVE_TIMEOUT;
    }

    // debug模式才打印
    if (GlobalConfig.isDebug) {
        print('请求异常: ' + error.toString());
        print('请求异常url: ' + url);
        print('请求头: ' + dio.options.headers.toString());
        print('method: ' + dio.options.method);
    }
    _error(errorCallBack, error.message);
    return '';
    }
    // debug模式打印相关数据
    if (GlobalConfig.isDebug) {
    print('请求url: ' + url);
    print('请求头: ' + dio.options.headers.toString());
    if (params != null) {
        print('请求参数: ' + params.toString());
    }
    if (response != null) {
        print('返回参数: ' + response.toString());
    }
    }
    String dataStr = json.encode(response.data);
    Map<String, dynamic> dataMap = json.decode(dataStr);
    if (dataMap == null || dataMap['state'] == 0) {
    _error(
        errorCallBack,
        '错误码:' +
            dataMap['errorCode'].toString() +
            ',' +
            response.data.toString());
    } else if (successCallBack != null) {
    successCallBack(dataMap);
    }
}

_error(Function errorCallBack, String error) {
    if (errorCallBack != null) {
    errorCallBack(error);
    }
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值