6、Flutterr聊天界面网络请求

news2024/12/26 9:20:41

一、准备网络数据

1.1 数据准备工作

  1. 来到网络数据制造的网址,注册登录后,新建仓库,名为WeChat_flutter;
  2. 点击进入该仓库,删掉左侧的示例接口,新建接口.

3. 接着点击右上角‘编辑’按钮,新建响应内容,类型为Array,一次生成50条

4. 点击chat_list左侧添加按钮,新建chat_list中的数据内容,此时用到一个获取随机头像的网站.到该网站中,随机复制一个图片地址,假设为:https://randomuser.me/api/portraits/women/35.jpg.将数据填上,然后保存.

5.接下来,我们想让获取的图像是个随机值,那么参考Mock.js网站中的生成规则.

6.接着回到响应内容这里,通过设置初始值规则,生成随机的图片地址.

  • https://randomuser.me/api/portraits/women/@natural(10,80).jpg

  • 接下来填充名称,消息的随机值.

  • 综上:服务器的数据准备工作完成,请求的链接地址

二、聊天界面导航条

  • 首先设置_RootPageState中进入App默认选中的NavigationBar的私有变量_currentIndex = 0,也就是默认选中微信界面.
  • 然后根据微信聊天界面的UI效果,我们先实现右上角的加号.

1. AppBar的actions就是我们需要添加操作的地方.

  • 按照这个思路继续,就需要自己实现一个弹出菜单的组件.然而这个时候,Flutter其实已经提供了一套成熟的控件以达到效果

2. PopupMenuButton组件

  • PopupMenuButton组件用来弹出一个菜单,必传参数为itemBuilder,用来实现它需要展示的内容.PopupMenuItem就是用来展示内容的类.PopupMenuButton有个onSelected属性,这个属性是个闭包,意思是选中某个PopupMenuItem的时候,会调用这个闭包.但是有个前提就是每个PopupMenuItem的value必须不为null的时候,才会执行onSelected闭包.
  • AppBar中具体内部实现为.
AppBar(
  //去除导航条黑线
  elevation: 0.0,
  backgroundColor: WeChatThemeColor,
  //设置标题默认居中、否则双端默认方式不一致
  centerTitle: true,
  title: const Text("微信", style: TextStyle(color: Colors.black),),
  actions: [
    Container(
      margin: EdgeInsets.only(right: 10),
      child: PopupMenuButton(
        onSelected: (item){
          print(item);
        },
        onCanceled: (){
          print('onCanceled');
        },
        //PopupMenuButton的背景颜色
        color: Colors.black,
        offset: Offset(0,60),
        child: Image(image: AssetImage('images/圆加.png'),width: 25,height: 25,),
        itemBuilder: (BuildContext context){
          return <PopupMenuItem>[
            _buildMenuItem('images/发起群聊.png','发起群聊'),
            _buildMenuItem('images/添加朋友.png','添加朋友'),
            _buildMenuItem('images/扫一扫1.png','扫一扫'),
            _buildMenuItem('images/收付款.png','收付款'),
          ];
        },
      ),
    )
  ],
),

3. 其中_buildMenuItem是我们封装的一个创建组件的方法,内部实现为

PopupMenuItem _buildMenuItem(String imageName,String title){
  return PopupMenuItem(
    value: {
      'imageName' : imageName,
      'title' : title,
    },
      child: Row(
        children: [
          Image(image: AssetImage(imageName), width: 25,),
          SizedBox(width: 10,),
          Text(title, style: TextStyle(color: Colors.white),),
        ],
      )
  );
}

4.关于PopupMenuButton背景颜色的设置.可以直接在其内部设置背景颜色.也可以在ThemeData中设置app的cardColor.但是优先级没有直接设置PopupMenuButton的高.如果不设置黑色背景颜色,弹出的视图显示均为白色,看不到UI效果.

三、请求网络数据

  1. 通过Dart packages 这个网站可以搜索flutter使用的包packages.我们使用http这个包来请求我们的网络数据.这个包是flutter官方提供的.实际项目开发的时候可能并不会使用http这个包,大部分是使用dio来请求网络数据.这里只介绍官方的http包如何使用.
  2. 导入http包.在名称后可以点击复制包名.

3.在项目的pubspec.yaml中粘贴复制的包名.

4. 粘贴完之后需要Pub get获取一下,获取包对应的代码.

  • 也可以在终端输入flutter packages get 来获取.

5.在chat_page.dart中导入http包并取别名

import 'package:http/http.dart' as http;

6.在渲染状态组件的时候发起网络请求,也就是在initState中发起网络请求.getData后采用async表示异步执行.async需要搭配await使用,await后面跟着的是耗时的代码,所以会异步执行调用.

class _ChatPageState extends State<ChatPage> {
    .....
    @override
    void initState() {
      super.initState();
      getDatas();
    }
    getDatas() async {
      var response = await http.get(Uri.parse('http://rap2api.taobao.org/app/mock/311243/api/chat/list'),);
      print(response.statusCode);//200
      print(response.body);//这里就是我们自定义的网络数据了
    }
    .....
}
  • 点击其他界面再次回到聊天界面会发现initState方法重新走了一遍,调用了网络请求,这是因为我么还没有保存住状态.后面将讲述如何保存Widget的状态.

7.处理返回数据

  • 首先介绍一下,在flutter中如何将请求返回的JSON数据转为Map,在我们iOS开发中是转为字典,而flutter中没有字典这个类型,对应的类型是Map.以及如何将Map转为JSON.在iOS中我们会使用一个NSJSONSerialization的类用来处理JSON数据.同样的,在flutter中也会有一个专门的类JsonCode来处理.

JSON和Map互相转换

  • 首先需要导入dart中的convert组件.
  • 然后我们写点测试用例,熟悉它的使用方式.
void initState() {
  super.initState();
  getDatas();
  final chat = {
    'name': '张三',
    'message': '在干嘛?',
  };
  //Map转JSON
  final jsonChat = json.encode(chat);
  print(jsonChat);
  //JSON转Map
  final mapChat = json.decode(jsonChat);
  print(mapChat);
  print(mapChat is Map);
}
  • 返回结果如下:
flutter: {"name":"张三","message":"在干嘛?"}
flutter: {name: 张三, message: 在干嘛?}
flutter: true
flutter: 200
  • 其中的json就是JsonCodec的实例. 'is'是用来判断是不是某个类型.

8. 新建聊天模型

  • 因为网络出来的数据可能为空,那么就需要用?来修饰定义的属性;
class Chat {
      final String? name;
      final String? message;
      final String? imageUrl;
      Chat(this.name,this.message,this.imageUrl);
      //工厂方法,用来初始化对象.
     factory Chat.fromJson(Map json){
       return Chat(json['name'],json['message'],json['imageUrl']);
     }
}
  • factory 关键字用来标记当前是工厂方法,是设计模式的一种,用来初始化对象.除了默认的构造方法,还可以使用这个工厂方法来实例化一个Chat对象.模型建立好了之后就可以处理响应的数据.
    • 如下: 模型数据成功转换.
//将json转为Chat模型
final chatModule = Chat.fromJson(mapChat);
print('name:${chatModule.name} message:${chatModule.message}');// name:张三 message:在干嘛? 

9.处理响应的数据

  • 首先我们会获取到通过网络接口获取的列表数据,但是不能保证网络请求一定会发送成功.所以要处理一些错误情况.在flutter中引入Future.表示接下来请求的数据,可能有值也可能没有值,一般与网络请求配合使用.
  • 因此返回值我们可以设定为.
Future<List<Chat>?> getDatas() async {}
  • 对于异常情况的处理,可以通过throw Exception的形式.
Future<List<Chat>?> getDatas() async {
  final response = await http.get(Uri.parse('http://rap2api.taobao.org/app/mock/311243/api/chat/list'));
  print(response.statusCode);
  if (response.statusCode == 200) {

  } else {
    throw Exception('statusCode: ${response.statusCode}');
  }
}
  • 接下来我们处理返回的body中的数据
    • 获取响应数据,并且转换为Map类型
//获取响应数据,并且转换成Map类型
final responseBody = json.decode(response.body);
//转换模型数组
responseBody['chat_list'].map(
    (item) {
      print(item);
      return item;
    }
);
  • 这样可以看到item的遍历数据.
flutter: {imageUrl: https://randomuser.mflutter: {imageUrl: https://randomuser.me/api/portraits/women/12.jpg, name: 黎超, message: 音和委起度明条部过们放省。们区以号还九保把王之候包与先件能议清。江知天能能五开比点别增石次米五平。极养提立手专把示低率号容眼组是石。离维照联子象派三热始受构参元离还。相电构次色影件力计面进东把。}
flutter: {imageUrl: https://randomuser.me/api/portraits/women/23.jpg, name: 傅秀兰, message: 但保写太满果此力少合反压色生太个图。制社并更个构北不张需国些清不。没八你或况铁员三时划志有改题头感。值年改你要变程新但八传织。进化林号中不按亲天张原美多。}e/api/portraits/women/37.jpg, name: 李丽, message: 可组品且发铁直报表状传素安小全。器音天石别数业局装共习清。加然处进派变装你农速约部族利音次层。毛得理状主质所局等工型即天研走机段。}
    • 接下来将其返回结果直接遍历为模型返回为List
final responseBody = json.decode(response.body);
//转换模型数组
List<Chat>chatList = responseBody['chat_list'].map<Chat>(
    (item) {
      return Chat.fromJson(item);
    }
).toList();
print(chatList);
return chatList;
  • 此时我们可以看到输出均为实例对象
[Instance of 'Chat', Instance of 'Chat', Instance of 'Chat', Instance of 'Chat', Instance of 'Chat',...] 
  • 上述可以直接采用箭头函数.这样我们就实现了响应数据的模型转换.
List<Chat>chatList = responseBody['chat_list'].map<Chat>((item) => Chat.fromJson(item)).toList();
return chatList;

10.处理网络请求的结果

  • 接下来我们要处理返回Future类型的异步网络请求结果.
    • 可以采用try...catch
    • 也可以采用then结合的形式
  • 这里我们使用then的方式处理结果, 输出其中的value.
loadData(){
  getDatas().then((value) {
    print(value);
  });
}
    • 这里可以看到value的结果就是我们的chatList数据.
  • 其实我们还可以采用一种更为简单的方式处理网络请求.在下一章讲解.

四、利用FutureBuilder渲染微信界面

  • 在flutter中渲染网络数据专门有个控件叫做FutureBuilder.当无数据时展示默认界面,有数据时继续渲染网络请求下来的数据

  • 此时可以看到返回的结果中 先是null、然后再是连续几次的数据.

  1. 此时我们可以通过snapshot的异步连接状态来查看.
  • 也就是snapshot.connectionState
    • 当处于waiting状态时,data会返回null
    • 当处于done的状态时,data会返回正常解析结果.
flutter: data: null
flutter: state:ConnectionState.waiting
flutter: data: [Instance of 'Chat', Instance of 'Chat', Instance of 'Chat', ...]
flutter: state:ConnectionState.done

    2. 所以这个时候我们可以借助于ConnectionState状态来确定当前要渲染的界面.

    • 当waiting状态时,展示一个Loading...
    • 当done状态时,渲染界面.
  • 因此我们的FutureBuilder的渲染实现部分为
FutureBuilder(
  future: getDatas(),
  builder: (BuildContext context, AsyncSnapshot snapshot){
     //无数据时渲染默认界面,有数据时显示网络数据
    print('state:${snapshot.connectionState}');
    if (snapshot.connectionState == ConnectionState.waiting) {
      return Center(child: Text('Loading...'),);
    } else {
      return ListView(
        children: snapshot.data.map<Widget>((item){
            return ListTile(
              //右侧 标题
              title: Text(item.name),
              //右侧 子标题
              subtitle: Container(
                height: 20,width: 20,
                //TextOverflow.ellipsis 展示不下的时候省略号
                child: Text(item.message,overflow: TextOverflow.ellipsis,),
              ),
              //左侧:圆型头像
              leading: CircleAvatar(
                backgroundImage: NetworkImage(item.imageUrl),
              ),
            );
        }).toList(),
      );
    }
  },
)
  • 展示的效果图如下:

  • 但是这样的渲染方式不是最好的.因为每次进入微信界面就需要发送网络请求.每次都要重新渲染.
    • 那么这种FutureBilder直接渲染布局的方式只能应用于数据相对简单的界面.
  • 也可以将请求下来的数据放入一个缓存模型数组中,当builder的时候再从模型数组中拿取使用.

五、网络请求的处理

  1. 这里我们将网络请求的数据进行处理.首先来到 _ChatPageState中,创建一个缓存数组
List<Chat> _datas = [];

      2. 在loadData时处理返回的数据.

  • 通过then将正常返回的数据赋值给缓存,然后在setState方法中实现这个赋值操作,就会引起界面的渲染.
  • 将错误的返回结果通过日志输出.
  • 会有类型不匹配的错误: 将datas设置为可空类型,然后在赋值的时候对空的情况进行空处理就行.
loadData(){
  //当数据正常返回的时候
  getDatas().then((List<Chat>? datas) {
     setState(() {
       _datas = datas ?? [];
     });
  }).catchError((err){
    print(err);
  });
}

3. 这个时候通过缓存的数据来渲染界面

  • Scaffold中body的FutureBuilder替换回Container.通过三目运算符判断当前缓存数组中是否有值,如果没有,就设置Loading.如果有值就渲染界面
Container(
  child: _datas.length == 0 ?
  Center(child: Text('Loading...'),)
      : ListView.builder(
      itemCount: _datas.length,
      itemBuilder: (BuildContext context, int index) {
        return ListTile(
          title: Text(_datas[index].name ?? ""),
          subtitle: Container(height: 20,width: 20,child: Text(_datas[index].message ?? ""),),
          leading: CircleAvatar(
            backgroundImage: NetworkImage(_datas[index].imageUrl ?? ""),
          ),
        );
    }),
),
  • 点击其他NavigationBar界面,再点回微信界面,会发现界面的渲染过程.

4. 关于Future请求结果的处理完善

  • Future请求结果的处理方面,除了catchError之外,还有whenComplete、timeout
loadData(){
  //当数据正常返回的时候
  getDatas().then((List<Chat>? datas) {
     setState(() {
       _datas = datas ?? [];
     });
  }).catchError((err){
    print(err);
  }).whenComplete(() {
    //数据处理完毕
    print("完毕");
  }).timeout(Duration(milliseconds: 10)).catchError((timeout){
    print("加载超时 ${timeout}");//flutter: 加载超时 TimeoutException after 0:00:00.010000: Future not completed
  });
}
  • 在这里,超时并不意味着请求结束,当请求结果返回之后,仍然调用了请求完毕.
  • 在这里,我们我们需要处理: 一旦请求发出,除非异常,否则超时后其他的数据都不应该返回去调用我们的setState渲染界面.

5. 请求超时的异常处理/多次重复刷新

  • 设置一个私有bool变量_cancelConnect, 如果当前的标记不为true,那么再去setState渲染界面.避免了数据污染.

  • 这个时候我们发现界面和通讯录界面都存在一种现象:当我们点击其他界面,再回到当前界面时,数据会重新加载.这个现象说明了我们需要进行状态的保存以避免重复刷新.接下来将对这个现象进行处理.

六、保存Widget的状态

关于状态的保存,这个时候我们引入另一个概念: 混入(Mixins),用来给类增加功能,是多继承模式下的一种代码复用.使用with关键字来实现混入一个或多个类.

  1. 因为flutter渲染效率非常高,当控件不在界面上展示的话就会被销毁,再次展示时会重新渲染.
  2. 如果我们的状态需要保存的话,就需要混入一个类:AutomaticKeepAliveClientMixin,也就是对ChatPage的延展.重写wantKeepAlive属性并且在build渲染方法中调用父类的渲染方法.
//AutomaticKeepAliveClientMixin让当前界面保存状态
class _ChatPageState extends State<ChatPage> with AutomaticKeepAliveClientMixin<ChatPage>{
.....
//保留setState状态
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
  //6.3 重写父类渲染方法
  super.build(context);
  ...
}
...
}

3. 同理我们去保存通讯录界面的状态.

4. 这个时候我们去检测设置的效果,发现貌似并没有设置成功.还是会重新渲染对应的界面.是否是设置失效了呢?

  • 其实不是.这个时候就需要考虑我们的根视图设置的问题了.因为之前预埋了坑点.

5. 回到rootpage.dart中,我们发现在设置当前显示body的时候,采用的是从_pages数组中获取对应的界面.在iOS中,这样设置并没有什么问题.

  • 但是在flutter中,这样设置,每次根据_currentIndex获取的视图显示对象并不是数组中设置的对象.
    • 因为在flutter中,在数组中创建的对象对于flutter来说只是一堆数据,通过build方法渲染到界面上.
    • 在build中有一个小部件树,这个小部件树是从MyApp开始build渲染,然后是它的home属性包含的RootPage对象,再通过RootPage中的设置的Container,去包含的ChatPage、FriendsPage等
MyApp => RootPage => Container => ChatPage/FriendsPage/DiscoverPage/MinePage
  • 一旦当前_currentIndex改变之后,那么设置的body就从_pages中获取到对应的界面对象.然而就是这个操作导致.当前Container包含的Page从一个切换到另一个,之前的界面就不在渲染树中.也就是被销毁了.

6. 回到我们在微信界面/通讯录界面混入AutomaticKeepAliveClientMixin这个类的目的:

    • 让小部件树之外指定的界面不要被销毁.也就是我们想要保留根视图下四个界面状态.当其中一个渲染在小部件树中的时候,另外三个不要被销毁.
  • 为了解决这个问题,我们引入flutter中另外一个控件PageController.

7. PageController设置rootpage根视图界面.

  • 首先创建一个私有变量PageController _controller, 并将初始界面page设置为第一个界面.
final PageController _controller = PageController(
   //初始显示的界面索引
   initialPage: 0,
);
  • 其次将Container中Scaffold的body设置为PageView
    • onPageChanged就是我们需要设置index改变的回调的地方
    • NeverScrollableScrollPhysics可以去除默认的左右滚动的效果.
PageView(
  onPageChanged: (int index ){
    _currentIndex = index;
    setState(() {
    });
  },
  //如果不设置这个属性,那么根视图事件可以左右滚动切换.
  physics: NeverScrollableScrollPhysics(),
  controller: _controller,
  children: [
    ChatPage(),
    FriendsPage(),
    DiscoverPage(),
    MinePage()
  ],
),
  • 综上:做完这些操作,我们再去点击任意界面,之前的状态就会被保留下来.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/493092.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试2023年最新题库(JAVA)

目录 华为OD机试是什么&#xff1f;华为OD面试流程&#xff1f;华为OD机试通过率高吗&#xff1f;华为OD薪资待遇&#xff1f;华为OD晋升空间&#xff1f;华为OD刷题列表&#xff0c;一天三题&#xff0c;刷出算法新高度&#xff0c;刷出人生新际遇。 大家好&#xff0c;我是哪…

什么是http代理504网关超时错误,要如何修复?

当你在使用 HTTP 代理时&#xff0c;有时候会遇到"504 网关超时"错误&#xff0c;这个错误看起来非常可怕&#xff0c;但实际上它并不是一个很难解决的问题。在本文中&#xff0c;我将向你介绍 504 错误的定义&#xff0c;以及为什么我们会遇到这个错误&#xff0c;同…

babysql

打开界面是一个登录框&#xff0c;所以直接使用的万能公式&#xff0c;但是没用出发了报错 结合提示来看&#xff0c;题目应该是过滤掉了or 尝试大小写绕过&#xff0c;失败了 尝试双写绕过&#xff0c;成功绕过限制 接下来就判断字段数&#xff0c;发现by也被过滤掉了 登是登上…

CAM350 PCB开短路检查指导

CAM350 PCB开短路检查指导 Layout完成后&#xff0c;通过DRC和华秋DFM检查没有问题后&#xff0c;使用CAM350进行开短路的检查&#xff0c;没有问题后可转交制版厂。 ①首先通过AD生成IPC文件&#xff0c;下图为生成步骤&#xff1a; File→Assembly Outputs→Test Point Repo…

新形势下,如何进行智慧园区移动应用建设?

智能化工园区通过信息化实现工业管理的数字化和网络化&#xff0c;实现对生产过程的全面监控和实时数据采集。这使企业能够更好地管理&#xff0c;及时发现问题并采取相应的措施来降低成本。此外&#xff0c;智慧化管理提高了企业资源的使用效率&#xff0c;避免浪费和重复利用…

异常___

规则&#xff1a;玩家是异常机器人&#xff0c;要突破正常机器人&#xff08;防火墙&#xff09;的扫描封锁攻击&#xff0c;到达目的地。 &#xff08;1&#xff09; 教学内容&#xff1a;指令的形式和运行方法。 简单的说就是脚本语言&#xff0c;指令的形式是给出固定顺序…

行为型模式-中介者模式

中介者模式 概述 一般来说&#xff0c;同事类之间的关系是比较复杂的&#xff0c;多个同事类之间互相关联时&#xff0c;他们之间的关系会呈现为复杂的网状结构&#xff0c;这是一种过度耦合的架构&#xff0c;即不利于类的复用&#xff0c;也不稳定。例如在下左图中&#xf…

协方差矩阵

目录 1.方差和协方差的定义 2.协方差矩阵 3. 协方差矩阵的应用 3.1 对两个类内协方差矩阵进行对角化 3.2 机器学习中的协方差矩阵应用小结 4. 协方差矩阵中心对齐 1.方差和协方差的定义 2.协方差矩阵 3. 协方差矩阵的应用 3.1 对两个类内协方差矩阵进行对角化 对两个…

【Linux】动态链接和静态链接

函数库一般分为静态库和动态库两种 动态库&#xff1a;使编译器对用户的程序进行动态链接 动态链接&#xff1a;拷贝的是动态库中当前程序所需代码的地址到可执行程序中的相关位置&#xff0c;可在执行时链接到动态库中的相关&#xff0c;即动态链接的可执行程序再运行时仍然依…

了解设计模式

https://github.com/WittyKyrie/UnityUtil/blob/main/%E5%B8%B8%E7%94%A8%E5%B7%A5%E5%85%B7/Object 代码仓库↑ 【游戏开发设计模式】单例模式&#xff0c;要提防的设计模式&#xff01;&#xff01;_哔哩哔哩_bilibili 参考↑ 组合模式&#xff1a; 继承会造成代码复用量…

Django框架的源码解析

简述从django-admin startproject [name]开始 小结 django.core.management init.py 1. 5个方法2. ManagementUtility 类 小结 base.py 1. 2个方法&#xff1a;2. CommandError(Exception):3. SystemCheckError(CommandError):4. CommandParser(ArgumentParser):5. DjangoHelpF…

【Gator Cloud】架构篇 - 提供基于云原生的数据安全保护

随着云计算的成熟和云计算系统的广泛使用&#xff0c;越来越多的企业选择将新业务部署到云上。但是&#xff0c;上云并不意味着就能够充分利用云平台的优势。目前&#xff0c;大部分的云化应用&#xff0c;依然还是基于传统的软件架构来搭建的&#xff0c;仅仅是移植到云上去运…

【python脚本系列】python脚本2——PDF转word文档

只需2行代码&#xff0c;轻松将PDF转换成Word 机器学习算法那些事 2023-05-05 18:58 发表于广东 编辑&#xff1a;数据分析与统计学之美 可将 PDF 转换成 docx 文件的 Python 库。该项目通过 PyMuPDF 库提取 PDF 文件中的数据&#xff0c;然后采用 python-docx 库解析内容的布局…

【面试题】关于JavaScript实现继承的六大方案,你都了解过吗?

​ 大厂面试题分享 面试题库 前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 web前端面试题库 VS java后端面试题库大全 前言 面试官&#xff1a;“你说说 JavaScript 中实现继承有哪几种方法&#xff1f;” …

相交链表 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

题目 解析 题目要求 如果相交 就返回交点如果不相交 就返回NULL 思路 1.通过题目的描述我们可以知道&#xff0c;两个单链表相交只有一种形式 并不存在下面的的形式 我们已经明确了单链表相交的形式&#xff0c; 那我们要如何判断两个单链表相交呢 这里给出一种做法&…

Mysql安装5分钟解决

文章目录 1.下载安装包&#xff1a;2.MySQL的初始配置3.安装mysql的服务&#xff1a;4.初始化MySQL命令&#xff1a;5.开启mysql服务命令&#xff1a;6.登录验证&#xff1a;7.修改密码&#xff1a; 1.下载安装包&#xff1a; 直接通过这里安装MYSQL5.7下载链接 或者进入MySQL…

干翻Mybatis源码系列之第七篇:Mybatis提供的集成缓存方案

第一章&#xff1a;Mybatis Orm的缓存 Mybatis定义了一个对象缓存&#xff0c;是Mybatis对缓存的封装&#xff0c;为了屏蔽实现的差异&#xff0c;这被定义成了一个接口Interface&#xff0c;这样的话&#xff0c;Mybatis的缓存基本上是存储于JVM内存中的。 一&#xff1a;Ca…

信息技术服务知识笔记

一、运维 1、基础环境运维服务 对保证信息系统正常运行所必需的电力、空调、消防、安防等基础环境的运维。包括&#xff1a;机房电力、消防、安防等系统的理性检查及状态监控、相应支持、故障处理、性能优化等服务 2、硬件运维服务 对硬件设备&#xff08;网络、主机、存储…

6.2.1mnist _eval

之前在调试6.2.1mnist _eval代码的时候&#xff0c;出现了下面的错误 //下面不阐述本人遇到的错误&#xff0c;直接告诉大家解决办法&#xff08;以老师给的源代码进行演示&#xff09; 首先&#xff0c;打开第6章的源代码 //点击程序与数据拆分的文件夹&#xff0c; 并将三个…

3、Flutter项目搭建

一、搭建项目 1.1 搭建空壳项目 接上篇的项目搭建、本篇将继续搭建各个界面.当BottomNavigationBar搭建起来后,在各个界面,没有显示对应的元素,因此我们在包含它的Scaffold中,添加body,这样让每个界面撑起来.每次点击就切换对应的界面. 那么我们创建一个_RootPageState中的私…