网络知识 娱乐 flutter基于provider状态管理设置主题颜色、实现简单登录、注册功能---页面+逻辑

flutter基于provider状态管理设置主题颜色、实现简单登录、注册功能---页面+逻辑

一、provider状态管理设置主题颜色在这里插入图片描述

第一步:
安装依赖库

provider: ^4.3.2+3

第二步:
创建共享数据模型

import 'package:flutter/material.dart';
import 'package:privider_test/base/baseThemes.dart';

class ThemesViewmodel extends ChangeNotifier {
  int _index = 0;
  int get getColor {
    return _index;
  }

  void SetColor(int value) {
    if (value > themes.length - 1) return;
    _index = value;
    notifyListeners();
  }
}

在main函数中引入共享模型
在这里插入图片描述

第三步:
创建base颜色数组

import 'package:flutter/material.dart';

List themes = [
  Colors.green,
  Colors.yellow,
  Colors.purple,
  Colors.orange,
  Colors.cyan,
  Colors.blue,
];

在这里插入图片描述
在主题中使用provider状态管理,由于想让颜色的值发生改变这里我们使用statefulWidget

mian.dart

import 'package:flutter/material.dart';
import 'package:privider_test/page/UserLoginpage.dart';
import 'package:provider/provider.dart';

import 'ViewModel/ThemesViewmodel.dart';
import 'base/baseThemes.dart';

void main() {
  runApp(MultiProvider(
    providers: [
      ChangeNotifierProvider(
        create: (context) => ThemesViewmodel(),
      )
    ],
    child: MyApp(),
  ));
}

class MyApp extends StatefulWidget {
  const MyApp({Key key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: UserLoginpage(),
      theme: ThemeData(
          primarySwatch:
              themes[Provider.of<ThemesViewmodel>(context).getColor]), //变换主题颜色
    );
  }
}

第四步:
画出ui,并添加点击事件

import 'package:flutter/material.dart';
import 'package:privider_test/ViewModel/ThemesViewmodel.dart';
import 'package:privider_test/base/baseThemes.dart';
import 'package:provider/provider.dart';
class UserLoginpage extends StatefulWidget {
  const UserLoginpage({ Key key }) : super(key: key);

  @override
  _UserLoginpageState createState() => _UserLoginpageState();
}

class _UserLoginpageState extends State<UserLoginpage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("登录界面"),
      ),
      body: Padding(
        padding: EdgeInsets.all(10),
        child: Container(
       child: ListView.builder(
         shrinkWrap: true,
         itemCount: themes.length,
         itemBuilder: _itemBuilder,//如果加()就是执行这个方法,不加就是将这个返回
       ), 
      ),
      )
    );
  }
  Widget _itemBuilder(BuildContext context,int index){
    return GestureDetector(
      onTap: ()async{
        (context).read<ThemesViewmodel>().SetColor(index);
      },
      child: Container(
        margin: EdgeInsets.symmetric(vertical: 8),
        height: 50,
        width: double.infinity,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(8),
        color: themes[index]
      ),
    ),
    );
  }
}

二、flutter登录功能的实现

第一步:创建目录文件夹
在这里插入图片描述
第二步:
配置yaml文件依赖

  provider: ^4.3.2+3
  dio: ^4.0.0
  tdui: 0.0.3
  encrypt: ^5.0.1
  # 提示框
  flutter_easyloading: ^3.0.0

编写global.dart

import 'package:dio/dio.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';

class Global {
  static Global _instance;
  Dio dio;
  String token;
  Map user;

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

  Global() {
    dio = new Dio();
    dio.options = BaseOptions(
      baseUrl: "https://zxw.td0f7.cn/",
      // baseUrl: "http://localhost:8080/",
      connectTimeout: 5000,
      sendTimeout: 5000,
      receiveTimeout: 5000,
      contentType: Headers.formUrlEncodedContentType,
      responseType: ResponseType.json,
    );
    dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) {
        EasyLoading.show(status: "Loading...");
        return handler.next(options); //continue
      },
      onResponse: (response, handler) {
        EasyLoading.dismiss();
        return handler.next(response); // continue
      },
      onError: (DioError e, handler) {
        print(e.toString());
        EasyLoading.dismiss();
        String msg = "";
        if (e.type == DioErrorType.connectTimeout) {
          msg = "连接超时错误";
        } else {
          msg = "接口错误!";
        }
        EasyLoading.showError(msg);
      },
    ));
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:myitem/router/route_handler.dart';
import 'package:myitem/view/UserLogin.dart';
import 'package:myitem/viewmodel/login_viewmodel.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (context) => LoginViewmodel(),
        )
      ],
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({Key key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const UserLogin(),
      onGenerateRoute: AppRouteManager.getInstance().onGenerateRoute,
      debugShowCheckedModeBanner: false, //去掉默认标签
    );
  }
}

loginmodel.dart

//登录数据模型
import 'package:myitem/global/Global.dart';
import 'package:myitem/util/rsa_utils.dart';

Future loginModel(String user, String pass) async {//将登录的账号和密码传入
  String pwd = await encodeString(pass);//使用rsa进行加密
  return await Global.getInstance().dio.post("/zxw/user",queryParameters: {
    "username":user,"password":pwd
  });//调用实例对象后的dio接口dio接口采用接口文档中对应的接口方式get/post提交数据,文档中
  //有固定传入参数两个主键请求的结果异步返回给viewmodel
}

/*  view层调用viewmodel,viewmodel通知model层,model再
发送请求返回给viewmodel,viewmodel处理返回结果并刷新view*/

登录界面

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:myitem/base/view.dart';
import 'package:myitem/util/rsa_utils.dart';
import 'package:myitem/viewmodel/login_viewmodel.dart';
import 'package:tdui/tdui.dart';
import 'package:provider/provider.dart';
class UserLogin extends StatefulWidget {
  const UserLogin({Key key}) : super(key: key);

  @override
  _UserLoginState createState() => _UserLoginState();
}

class _UserLoginState extends State<UserLogin> {
  @override
  void initState() { 
    super.initState();

  }
  // void loadData()async{
  //   var result = await encodeString("1");
  //   print(result);
  // }
  @override
  void dispose() {
    super.dispose();//节省资源
    context.read<LoginViewmodel>().getPwd.dispose();
    context.read<LoginViewmodel>().getUser.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: getAppBar("登录"),
      body: Padding(
        padding: EdgeInsets.all(20),
        child: Column(
          children: [
            // Image.asset(
            //   "images/login.jpg",
            //   width: double.infinity,
            //   fit: BoxFit.fill,
            // ),
            SizedBox(
              height: 16,
            ),
            TextField(
              decoration: InputDecoration(
                labelText: "账号",
                hintText: "请输入账号",
                prefix: Icon(Icons.person),
              ),
              autofocus: true,
              textInputAction: TextInputAction.next,
              controller: Provider.of<LoginViewmodel>(context).getUser,
            ),
            TextField(
              controller: Provider.of<LoginViewmodel>(context).getPwd,
              decoration: InputDecoration(
                  labelText: "密码", hintText: "请输入密码", prefix: Icon(Icons.lock)),
              obscureText: true,
              textInputAction: TextInputAction.send,
            ),
            SizedBox(
              height: 16,
            ),
            GestureDetector(
              child: Container(
                width: double.infinity,
                child: Text(
                  "找回密码",
                  style: TextStyle(color: Colors.blue),
                  textAlign: TextAlign.right,
                ),
              ),
              onTap: () {
                print("找回密码");
              },
            ),
            SizedBox(
              height: 16,
            ),
            TdButton(
              '登录',
              theme: TdButtonType.primary,
              loading: Provider.of<LoginViewmodel>(context).getIsLogin,
              onClick: () {
                _login();
                // loadData();
              },
            ),
            SizedBox(
              height: 16,
            ),
            TdButton(
              '注册',
              theme: TdButtonType.primary,
              onClick: () {
                _register();
              },
            )
          ],
        ),
      ),
    );
  }

  void _login() {
    // context.read().setIsLogin(true);
    // new Timer(Duration(seconds: 3), () {
    //   context.read().setIsLogin(false);
    //   Navigator.of(context).pushNamed("/MenuPage");
    // });
    
    context.read<LoginViewmodel>().login(context);
  }

  void _register() {
    // context.read().setIsLogin(false);
    Navigator.of(context).pushNamed("/RegisterPage");
  }
}
/*  view层调用viewmodel,viewmodel通知model层,model再
发送请求返回给viewmodel,viewmodel处理返回结果并刷新view*/


login_viewmodel

import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:myitem/model/login_model.dart';
import 'package:tdui/tdui.dart';

//创建登录状态管理
class LoginViewmodel extends ChangeNotifier {
  bool _isLogin = false;
  TextEditingController _userName; //创建controller进行全局状态管理
  TextEditingController _password;
  bool get getIsLogin {
    //返回
    return _isLogin;
  }

  TextEditingController get getUser {
    _userName ??= TextEditingController();
    //返回
    return _userName;
  }

  TextEditingController get getPwd {
    _password ??= TextEditingController(); //如果没有创建那么进行实例化
    //返回
    return _password;
  }

  // ignore: avoid_return_types_on_setters
  void setIsLogin(bool value) {
    _isLogin = value;
    notifyListeners();
  }

  void login(BuildContext context) async {
    setIsLogin(true); //先设置为true
    if (getUser.text.isEmpty) {
      //判断账号是否为空
      TdToast.fail(context)(message: "账号不能为空");
      setIsLogin(false); //如果为空那么就返回false
      return;
    } else if (getPwd.text.isEmpty) {
      //如果密码为空,那么返回false
      TdToast.fail(context)(message: "密码不能为空");
      setIsLogin(false);
      return;
    }
   //如果账号密码都不是空那么,用response接收账号和密码从viewmodel传值到数据模型
      Response result = await loginModel(getUser.text, getPwd.text);
      if (result.data["success"]) {

        Navigator.of(context).popAndPushNamed("/MenuPage");
      } else {
        TdDialog.alert(context)(result.data["msg"],
            theme: TdDialogTheme.android);
      }
      setIsLogin(false);
    
  }
}

在这里插入图片描述

   theme: ThemeData(primarySwatch: Colors.yellow),//变换主题颜色

实现开关功能

在这里插入图片描述
在这里插入图片描述

  TdCell(
              label: "出生日期",
              align: Alignment.center,
              content: Provider.of<RegisterViewModel>(context).getDateTime,
              footer: Row(
                children: [
                  TdSwitch(
                    checked:
                        Provider.of<RegisterViewModel>(context).getSolar == 0
                            ? false
                            : true,
                    onChange: (v) {
                      setState(() {
                        (context).read<RegisterViewModel>().SetSolar(v ? 1 : 0);
                      });
                    },
                  ),
                  SizedBox(
                    width: 8,
                  ),
                  Text(Provider.of