【Flutter】第一篇基础:站在一名web前端开发者的角度看代框架

news2025/3/13 10:41:47

Flutter

Flutter 是一个跨平台的 UI 工具集,它的设计初衷,就是允许在各种操作系统上复用同样的代码,例如 iOS 和 Android,同时让应用程序可以直接与底层平台服务进行交互。如此设计是为了让开发者能够在不同的平台上,都能交付拥有原生体验的高性能应用,尽可能地共享复用代码的同时,包容不同平台的差异。

如果你直接安装flutter就不需要安装dart了,因为flutter已经包含了dart环境了

所以推荐直接安装flutter即可

安装dart

首先你需要先安装homebrew,homebrew是一个软件资源包管理工具

安装homebrew

外网环境
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
推荐国内镜像
/bin/bash -c "$(curl -fsSL https://gitee.com/wejectchan/brew/raw/master/install.sh)"

安装dart

brew tap dart-lang/dart
brew install dart

安装Flutter

苹果电脑芯片有两种,一种是intel芯片(X86),一种是M系列芯片(Arm)

查看系统芯片

uname -a

注意安装一定要根据系统芯片来安装

具体查看

https://flutter.cn/docs/get-started/install/macos
第一步先下载对应系统版本的压缩包
Intel芯片
intel:https://storage.flutter-io.cn/flutter_infra_release/releases/stable/macos/flutter_macos_3.13.7-stable.zip
M系列芯片
https://storage.flutter-io.cn/flutter_infra_release/releases/stable/macos/flutter_macos_arm64_3.13.7-stable.zip
第二步解压到某一个文件路径
 cd ~/development
 unzip ~/Downloads/flutter_macos_3.13.7-stable.zip
第三步配置环境变量
export PATH="$PATH: 文件路径/flutter/bin"

这里需要注意,这样配置仅仅在当前命令窗生效,要永久生效则需要配置到shell文件中

永久配置具体看这里
https://flutter.cn/docs/get-started/install/macos#update-your-path
打开或者创建 shell 的 rc 文件,比如,在 Linux 和 macOS Mojave 或 Mojave 之前的系统里,是默认使用 Bash 的,所以需要修改 $HOME/.bashrc 文件。 macOS Catalina 操作系统默认使用 Z Shell,所以需要修改 $HOME/.zshrc 文件。请知晓,如果你使用不同的 shell,文件目录或文件名可能会有所不同。
老旧的版本
vim ~/.bash_profile 
或者open ~/.bash_profile


最新版的系统都使用zshrc 
vim ~/.zshrc 
或者open ~/.zshrc


export PATH="$PATH: 文件路径/flutter/bin"
source $HOME/.bash_profile 来刷新当前命令行窗口。
通过运行以下命令来验证 flutter/bin 文件夹是否已经添加到 PATH 环境变量中:
 echo $PATH
验证 flutter 命令是否可用,可以执行下面的命令检测:
which flutter

安装苹果模拟器

你只需要从应用商店下载Xcode进入之后会提示你下载模拟器,按要求下载即可

不过通常会下载失败,因为模拟器镜像在国外,如果你有苹果开发者帐号可以通过抓取下载链接的形式去进行直接下载

没有开发者帐号下载失败就多次重试,一般3到4次即可

开发工具

可以使用vscode或者Xcode(苹果)||Android Studio(安卓)

推荐使用VScode

使用vscode可以在扩展中搜索flutter相关扩展和dart,以便代码提示和自动导入文件

Dart

Flutter

Awesome Flutter Snippets

创建项目

如果你有Xcode或者Android Studio,直接创建Flutter项目即可

如果你是用vscode则需要使用命令行去进行创建

flutter create flutter02
code .
flutter run
flutter devices //使用真机运行

最重要的就是lib文件夹以及pubspec.yaml文件,平台文件一般不需要理会

我们编写代码都是在lib文件夹下进行编写

使用第三方插件

进入官方网站搜索插件(推荐使用加速器):

https://pub.dev/

进入之后搜索所需插件的安装方式即可

这里的重点是安装之后运行到模拟器这一步可能会出现cocospods安装失败甚至安装之后无法使用的问题。

cocospods安装问题

首先你需要安装homebrew,这里前面有教程不再赘述

第二步,检查ruby版本,输入命令ruby -v,这里m系列芯片的电脑默认是自带ruby的,但是版本过低,我们需要更新ruby

使用:

brew install ruby

默认会下载最新的版本

同时记得要去bash_profile编辑环境变量,否则可能会出现ruby系统版本没有改变的问题

export PATH=/opt/homebrew/opt/ruby@3.2/bin:$PATH

查看ruby安装路径,可以在/opt/homebrew/opt目录中查看

最关键的就是更新gem版本,这一步就会下载cocoapods

sudo gem update --system -n /usr/local/bin

可以通过查看命令判断cocoapods是否成功下载

gem list

如果出现cocoapods相关多个软件,说明安装成功

输入命令:判断是否安装成功,如果成功,只会返回版本号,否则都算不成功

pod --version

注意

如果输入pod --version出现报错,很可能是由于gem中的activeSupport版本有bug,这个时候你需要安装稳定版的activeSupport 7.0.8,有问题的版本就是7.1.0之后的版本

sudo gem install activesupport -v 7.0.8 
sudo gem uninstall activesupport -v 最新版

这样就可以使用第三方插件并运行在模拟器上面了。

Flutter 教程系列

与其说是教程,不如说是讲如何站在前端的角度去看待Flutter框架,推荐安装Getx配合使用,Flutter是一款轻量级的框架,很多额外的功能都使用插件来配合完成。

所以,你可以像这样安装我的依赖

dependencies:
  fluttertoast: ^8.2.2
  get:
  dio: ^5.3.3
  webview_flutter: ^4.4.1

配置环境变量

FLUTTER_STORAGE_BASE_URL :https://storage.flutter-io.cn

这样使用Flutter run命令可能会出现如下情况:

Flutter assets will be downloaded from https://storage.flutter-io.cn. Make sure you trust this source!

无需理会!

配置安卓gradle环境

第一处:

buildscript {
    ext.kotlin_version = '1.7.10'
    repositories {
    	//看这里
        // google()
        // mavenCentral()
        maven { url 'https://maven.aliyun.com/repository/public' }
        maven { url 'https://maven.aliyun.com/repository/google' }
        // maven { url 'http://maven.aliyun.com/nexus/content/groups/public'}
        maven { url 'https://maven.aliyun.com/repository/gradle-plugin'} 
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:7.3.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

第二处:

allprojects {
    repositories {
    //看这里
        // google()
        // mavenCentral()
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/public' }
        // maven { url 'http://maven.aliyun.com/nexus/content/groups/public'}
        maven { url 'https://maven.aliyun.com/repository/gradle-plugin'}
    }
}

配置苹果环境变量

open ~/.bash_profile

export path:flutter安装路径:PATH

路由

原生Flutter有自己的路由方式

跳转到下一个页面

第一种方式:(要传递参数直接放入即可)
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
      //跳转并传参
      return const SearchPage(
         title: '你好',
        );
      }))
第二种方式:通过路由名称,也可以传递参数
Navigator.of(context).pushNamed("/pagebuilder",arguments: {})

注意,这种方式需要提前定义好路由栈初始化路由

在main.dart中进行定义:

class MyApp extends StatelessWidget {
  MyApp({super.key});


  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      //初始化路由
      initialRoute: "/",
      //定义路由栈
       routes: router(context),
    );
  }
}

router(context) {
  return {
    "/pageanmation": (context) => const MyAnmationList(),
    "/pagefull": (context) => const PageFullDemo(),
    "/pagebuilder": (context) => const PageBuilderDemo(),
    "/pageview": (context) => const MyPageView(),
    "/dialog": (context) => const DialogPage(),
    "/login": (context) => const LoginPage(),
    "/register": (context) => const RegisterPage(),
    "/search": (context) => const SearchPage(),
    "/": (context) => const MyTabs(),
    "/categroy": (context) => const CatrgroyPage()
  };
}

第三种方式:推荐使用Getx

Getx拥有强大的统一的路由管理:

 Get.toNamed("/search?hello=11111", arguments: {"msg": "hello"});
 
 Get.to(NextScreen());

在main.dart中这样配置:

getPages引入路由文件,使用GetMaterialApp强化MaterialApp

//引入路由
import './router/index.dart';

class MyApp extends StatelessWidget {
  MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      //去除debug
      debugShowCheckedModeBanner: false,
      title: "Flutter Demo",
      //初始化路由
      initialRoute: "/",
      // 以后统一使用这种方式去管理路由
      getPages: AppPage.routes,
    );
  }
}

新建一个router文件夹统一管理

import 'package:get/get.dart';
//导入页面
import '../page/tabs.dart';
import '../page/search.dart';
import '../page/tabs/categroy.dart';
import '../page/login.dart';
import '../page/register.dart';
import '../page/dialogdemo.dart';
import '../page/pageviewdemo.dart';
import '../page/pageviewbuilder.dart';
import '../page/pageFulldemo.dart';
import '../page/anmationListDemo.dart';
import '../page/getxstatedemo.dart';
import '../page/inputdemo.dart';
import '../page/webviewdemo.dart';
import '../page/i18ndemo.dart';
//引入中间件
import 'middleware/shopMiddleware.dart';

class AppPage {
  static final routes = [
    GetPage(
      name: "/",
      page: () => const MyTabs(),
      transition: Transition.leftToRight, //设置单个页面跳转的方式
      // middlewares: [MiddlePageVC()],//设置中间件(GetPage),可以根据优先级设置多个中间件
    ),
    GetPage(
        name: "/pagefull",
        page: () => const PageFullDemo(),
        transition: Transition.rightToLeft, //设置单个页面跳转的方式
        middlewares: [shopMiddleware()]), //设置中间件(GetPage),可以根据优先级设置多个中间件
    GetPage(
        name: "/pageanmation",
        page: () => const MyAnmationList(),
        transition: Transition.leftToRight //设置单个页面跳转的方式
        ),
    GetPage(
        name: "/pagebuilder",
        page: () => const PageBuilderDemo(),
        transition: Transition.leftToRight //设置单个页面跳转的方式
        ),
    GetPage(
        name: "/pageview",
        page: () => const MyPageView(),
        transition: Transition.leftToRight //设置单个页面跳转的方式
        ),
    GetPage(
        name: "/dialog",
        page: () => const DialogPage(),
        transition: Transition.rightToLeft //设置单个页面跳转的方式
        ),
    GetPage(
        name: "/login",
        page: () => const LoginPage(),
        transition: Transition.leftToRight //设置单个页面跳转的方式
        ),
    GetPage(
        name: "/register",
        page: () => const RegisterPage(),
        transition: Transition.leftToRight //设置单个页面跳转的方式
        ),
    GetPage(
        name: "/search",
        page: () => const SearchPage(),
        transition: Transition.leftToRight //设置单个页面跳转的方式
        ),
    GetPage(
        name: "/categroy",
        page: () => const CatrgroyPage(),
        transition: Transition.leftToRight //设置单个页面跳转的方式
        ),
    GetPage(
        name: "/mygetx",
        page: () => MyGetXState(),
        transition: Transition.leftToRight //设置单个页面跳转的方式
        ),
    GetPage(
        name: "/myinput",
        page: () => MyInputPage(),
        transition: Transition.rightToLeft //设置单个页面跳转的方式
        ),
    GetPage(
        name: "/mywebview",
        page: () => const MyWebviewPage(),
        transition: Transition.rightToLeft //设置单个页面跳转的方式
        ),
    GetPage(
        name: "/myi18n",
        page: () => const MyI18NPage(),
        transition: Transition.rightToLeft //设置单个页面跳转的方式
        ),
  ];
}


最重要的是它可以每一个页面不同的跳转动画和方式以及中间件,非常适合企业级业务需求,例如跳转登录。

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter/cupertino.dart';

class shopMiddleware extends GetMiddleware {
  @override
  RouteSettings? redirect(String? route) {
    print(route);
    // return null;
    //没有权限跳转到登录页面
    return const RouteSettings(name: "/login", arguments: {"msg": "你还未登录!"});
  }
}

获取数据

如果你使用Getx

Get.arguments
Get.parameters

如果不使用Getx,你需要提前定义对应的变量,注意把const移除掉,因为你已经不属于一个静态页面了

final String title;

  SearchPage({Key? key, required this.title}) : super(key: key);
  
  
  //使用
  (title: Text(widget.title)

返回上一个页面

第一种方式
Navigator.pop(context)
第二种方式
Navigator.of(context).pop("好的");

//直接跳转到message页面,这种跳转方式相当于redirect,会删除前面一个页面
Navigator.of(context).pushAndRemoveUntil(
     MaterialPageRoute(builder: (context) {
                  return const MessagePage();
                }), (route) => false);
                
//使用替换路由跳转,相当于干掉前一个页面
Navigator.of(context).pushReplacementNamed("/home")
第三种方式(Getx推荐)

要关闭snackbars, dialogs, bottomsheets或任何你通常会用Navigator.pop(context)关闭的东西。

Get.back();

进入下一个页面,但没有返回上一个页面的选项(用于闪屏页,登录页面等)。

Get.off(NextScreen());

进入下一个页面并取消之前的所有路由(在购物车、投票和测试中很有用)

如果你熟悉uniapp的话,这个相当于redirect

Get.offAll(NextScreen());

状态管理

注意:这里仅仅站在前端的角度去做

这里仅使用Getx进行状态管理,如果你熟悉前端的话,这一步相当于vue的vuex,react的redux。

新建一个store文件夹

index.dart,这是一个统一管理所有状态的文件,

Get.put方法运行放入一个控制器,这个控制器你可以把它当成一个全局的公共变量,放入之后Getx会进行内部的管理和追踪

//类似于vuex

import 'package:get/get.dart';

import './user.dart';

//统一管理所有的store
class Store {
  static final Store _instance = Store._internal();

  factory Store() {
    return _instance;
  }
  //将所有的store都放入这里
  Store._internal() {
    Get.put(UserController());
  }
}

通过继承GetxController使其变成一个可以追踪的控制器,并暴露出响应式变量和函数,这一步相当于暴露出所有的state,函数就是用来改变state的函数,相当于mutation

import 'package:get/get.dart';

class UserController extends GetxController {
  //这里定义变量
  RxInt count = 0.obs;

  //重置函数
  void reset() {
    count.value = 0;
  }

  //这里定义函数
  void increment() {
    count.value++;
  }
}

最后,在main.dart进行引入

import './store/index.dart';

void main() {
  Store(); // 初始化Store实例
  runApp(MyApp());
}

这样,你就可以在App所有的页面拿到这些数据了,如何获取呢,

既然有put的操作,就有find的操作

Get.find函数非常强大,他能找到对应的控制器

  final UserController userController = Get.find<UserController>();

所有的数据就在userController中:

注意:为了改变数据能够响应式的变化布局,因此,你需要使用Obx函数对响应式数据进行追踪,相当于前端的观察者模式

import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../../store/user.dart';

class CatrgroyPage extends StatefulWidget {
  const CatrgroyPage({super.key});

  @override
  State<CatrgroyPage> createState() => _CatrgroyPageState();
}

class _CatrgroyPageState extends State<CatrgroyPage> {
  //通过Get.find获取同一个控制器实例,可以使用数据,注意,只有先put控制器,才能find,否则会报错
  final UserController userController = Get.find<UserController>();

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(children: [
        Obx(() => Text('分类当前store里面的数值: ${userController.count.value}')),
        ElevatedButton(
            onPressed: () {
              //不建议这么改,这样会导致数据的改变无法追踪,尽量调用方法去使用
              // userfind.count.value = 10;
              //建议这么修改
              userController.reset();
            },
            child: const Text("重置"))
      ]),
    );
  }
}

看到这里,如果你是一名前端,你可以简单的把它理解成,通过定义一个函数,把函数放入Getx(put)中,Getx就可以自动帮你管理,要使用就拿出来(find),同时数据的改变要引起页面的重新渲染,需要使用观察者(Obx)通知Getx对页面进行改变,是不是有vue的双向绑定的意思了。

如果你不使用Getx,但是你的数据改变没有引起页面的变化,你需要看看是否使用了setState函数,这跟React的思路是一样的,如果你了解React,你就明白什么意思了。

Webview

这里使用Webiew_Flutter插件来实现,这是官方提供的webview插件

这里仅使用于安卓或苹果移动端设备,不适用于web

下载依赖

 webview_flutter: ^4.4.1

开启权限

安卓需要开启网络权限,默认是开启的

苹果需要配置ios/Runner/info.plist文件,加上这个

	<!-- 使ios运行运行webview -->
 	<key>io.flutter.embedded_views_preview</key>
    <string>YES</string>

使用

第一步,先声明一个weviewController

  late WebViewController controller;

第二步,在 initState 中初始化 controller

  void initState() {
    //第二步,在 initState 中初始化 controller
    controller = WebViewController()
	      //默认是不开启的,手动开启支持js
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
     ..loadRequest(Uri.parse('https://www.csdn.net/'), headers: {})
    super.initState();
  }

第三步,使用WebViewWidget,使用sizebox可以控制大小

        SizedBox(
            height: 400,
            child: WebViewWidget(
                //控制器
                controller: controller,
   )),

这样就大功告成了,你就可以在页面上面看到webview页面了

手势操作,在WebViewWidget配置第二个参数

                //手势操作
                gestureRecognizers: {
                  Factory<VerticalDragGestureRecognizer>(
                    () {
                      return VerticalDragGestureRecognizer()
                        ..onStart = (DragStartDetails details) {
                          print("start");
                        }
                        ..onDown = (DragDownDetails details) {
                          print("down: $details");
                        };
                    },
                  )
                }

设置UA

 ..setUserAgent(
          // "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"
          "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36")

路由操作:这个非常种要,可以追踪链接变化,注入JS,拦截等操作

      ..setNavigationDelegate(NavigationDelegate(
        //   //页面开始请求,获取页面请求
        onNavigationRequest: (requset) {
          print("页面请求参数 ${requset.url}");
          return NavigationDecision.navigate;
        },
        //   //页面开始加载
        //   onPageStarted: (url) {},
        //页面加载完毕,注入js,既使 WebView 加载的页面中可能还有链接,跳到另一个地址,js 注入的代码依然有效!
        onPageFinished: (url) async {
          var cookie = await controller
              .runJavaScriptReturningResult('document.cookie') as String;

          var ua = await controller
              .runJavaScriptReturningResult('navigator.userAgent;') as String;
          print("当前页面的cookie:$cookie,当前的ua是 $ua");
        },
        //   //加载错误
        //   onWebResourceError: (error) {
        //     print(error);
        //   },
      ));

国际化

使用Getx进行国际化配置非常简单,这里站在前端角度去进行配置

建立一个i18n文件夹,统一管理在index

import 'package:get/get.dart';
import './zh_CN.dart';
import './en_US.dart';

class Messages extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
        ...ZhCN().keys,
        ...EnUS().keys,
      };
}

en_US

import 'package:get/get.dart';

class EnUS extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
        'en_US': {
          'hello': 'hello world',
        },
      };
}

zh_CN

import 'package:get/get.dart';

class ZhCN extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
        'zh_CN': {
          'hello': '你好 世界',
        },
      };
}

在main.dart进行配置

 import 'i18n/index.dart';
 
 
 @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      //去除debug
      debugShowCheckedModeBanner: false,
      title: "Flutter Demo",
      //初始化路由
      initialRoute: "/",
      //命名路由
      // routes: router(context),
      // 以后统一使用这种方式去管理路由
      getPages: AppPage.routes,
      translations: Messages(), // 你的翻译
      locale: Locale('zh', 'CN'), // 将会按照此处指定的语言翻译
      fallbackLocale: Locale('en', 'US'), // 添加一个回调语言选项,以备上面指定的语言翻译不存在
      // locale: ui.window.locale,  //读取系统语言
    );
  }

使用:

 Text('hello'.tr)

改变语言

 Get.updateLocale(Locale('en', 'US'));
 Get.updateLocale(Locale('zh', 'CN'));

非常简单,这样,你只需要在不同地区配置不同文件即可。

样式和布局

样式和布局可以查看我项目代码中的demo,每一个样式文件都有命名标识,如果要运行查看,直接复制替换到main.dart进行运行查看即可,这里不多赘述,样式和布局多敲就可以。

或者运行项目,点击查看对应的效果,结合代码进行查看。

网络Api

具体可以看我代码中的api部分

国际化

使用Getx进行国际化配置非常简单,这里站在前端角度去进行配置

建立一个i18n文件夹,统一管理在index

import 'package:get/get.dart';
import './zh_CN.dart';
import './en_US.dart';

class Messages extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
        ...ZhCN().keys,
        ...EnUS().keys,
      };
}

en_US

import 'package:get/get.dart';

class EnUS extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
        'en_US': {
          'hello': 'hello world',
        },
      };
}

zh_CN

import 'package:get/get.dart';

class ZhCN extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
        'zh_CN': {
          'hello': '你好 世界',
        },
      };
}

在main.dart进行配置

 import 'i18n/index.dart';
 
 
 @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      //去除debug
      debugShowCheckedModeBanner: false,
      title: "Flutter Demo",
      //初始化路由
      initialRoute: "/",
      //命名路由
      // routes: router(context),
      // 以后统一使用这种方式去管理路由
      getPages: AppPage.routes,
      translations: Messages(), // 你的翻译
      locale: Locale('zh', 'CN'), // 将会按照此处指定的语言翻译
      fallbackLocale: Locale('en', 'US'), // 添加一个回调语言选项,以备上面指定的语言翻译不存在
      // locale: ui.window.locale,  //读取系统语言
    );
  }

使用:

 Text('hello'.tr)

改变语言

 Get.updateLocale(Locale('en', 'US'));
 Get.updateLocale(Locale('zh', 'CN'));

非常简单,这样,你只需要在不同地区配置不同文件即可。

样式和布局

样式和布局可以查看我项目代码中的demo,每一个样式文件都有命名标识,如果要运行查看,直接复制替换到main.dart进行运行查看即可,这里不多赘述,样式和布局多敲就可以。

或者运行项目,点击查看对应的效果,结合代码进行查看。

真机测试

安卓机型

如果你使用安卓设备进行测试的话,仅需要开启开发者模式并将手机连接到电脑设备上选择传输文件即可

苹果机型

如果你是iOS设备的话,请仔细看以下步骤:

第一步,你需要描述文件和p12证书,这两个东西你只能从开发者账号中去获取

双击打开p12证书,这时候系统会弹出弹窗,请输入证书密码,并将证书放入登录(在弹窗的右下角有选项)

在这里插入图片描述

第二步,打开Flutter项目,点击ios/Runner.xcworkspace文件,这个时候会自动打开Xcode,请你配置上对应的包名以及p12文件,没有出现红色警告说明配置成功,这个时候只需要点击左上角的运行命令即可。
在这里插入图片描述

第三步,后续就可以直接在vscode中运行即可,可以不需要在xcode中打开。

项目代码

项目代码

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

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

相关文章

怎么把m4v转换为mp4?

怎么把m4v转换为mp4&#xff1f;M4V是一种由苹果公司开发的视频文件格式&#xff0c;该格式可以在苹果公司的iTunes和QuickTime软件中播放。M4V格式本质上与MP4格式相似&#xff0c;但M4V通常包括了用于数字版权管理&#xff08;DRM&#xff09;的保护措施&#xff0c;以控制该…

【笔记-OrCAD】WARNING(ORCAP-36038)解决办法

问题描述&#xff1a; OrCAD16.6绘制好原理图后&#xff0c;点击“*.dsn”文件可以生成网表&#xff0c;在存放原理图的文件内找到allegro文件夹&#xff0c;用记事本打开netlist.log文件&#xff0c;可以看到具体的警告原因&#xff0c;例如&#xff1a; WARNING(ORCAP-36038)…

优雅而高效的JavaScript—— Class 和模块化

&#x1f60a;博主&#xff1a;小猫娃来啦 &#x1f60a;文章核心&#xff1a;优雅而高效的JavaScript—— Class 和模块化 文章目录 引言Class 的概念和用法Class 的定义Class 的继承Class 的静态方法和属性 模块化的概念和用法模块的导出和导入模块的默认导出和命名导出模块的…

SpringCloud: sentinel链路限流

一、配置文件要增加 spring.cloud.sentinel.webContextUnify: false二、在要限流的业务方法上使用SentinelResource注解 package cn.edu.tju.service;import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockExcept…

CVPR、ICCV、ECCV论文获取

CVPR每年召开&#xff0c;ICCV两年一次 链接地址 ECCV两年一开 链接地址

10. 机器学习-评测指标

Hi,你好。我是茶桁。 之前的课程中&#xff0c;我们学习了两个最重要的回归方法&#xff0c;一个线性回归&#xff0c;一个逻辑回归。也讲解了为什么学习机器学习要从逻辑回归和线性回归讲起。因为我们在解决问题的时候&#xff0c;有限选择简单的假设&#xff0c;越复杂的模型…

十七、文件(1)

本章概要 文件和目录路径 选取路径部分片段路径分析Paths 的增减修改 目录 在丑陋的 Java I/O 编程方式诞生多年以后&#xff0c;Java终于简化了文件读写的基本操作。 打开并读取文件对于大多数编程语言来说是非常常用的&#xff0c;由于 I/O 糟糕的设计以至于很少有人能够在不…

第七章 排序

第七章 排序 概述插入排序交换排序冒泡排序快速排序 选择排序直接选择排序堆排序 归并排序有序序列合并二路归并排序 小试牛刀 概述 排序就是将一组对象按照规定的次序&#xff08;升序或降序等&#xff09;重新排列的过程&#xff0c;往往为检索服务相同键值的两个记录在排序…

索引背后的数据结构——B+树

为什么要使用B树&#xff1f; 可以进行数据查询的数据结构有二叉搜索树、哈希表等。对于前者来说&#xff0c;树的高度越高&#xff0c;进行查询比较的时候访问磁盘的次数就越多。而后者只有在数据等于key值的时候才能进行查询&#xff0c;不能进行模糊匹配。所以出现了B树来解…

SQL数据库管理工具RazorSQL mac中文版特点与功能

RazorSQL mac是一款功能强大的SQL数据库管理工具&#xff0c;它支持多种数据库&#xff0c;包括MySQL、Oracle、Microsoft SQL Server、SQLite、PostgreSQL等。 RazorSQL mac 软件特点和功能 多种数据库支持&#xff1a;RazorSQL支持多种数据库&#xff0c;用户可以通过一个工…

故障预测与健康管理(PHM)在工业领域的发展前景

故障预测与健康管理&#xff08;PHM&#xff09;作为一种关键技术&#xff0c;已经在工业领域引起了广泛的关注和应用。PHM利用传感器、数据科学和智能算法等技术手段&#xff0c;通过实时监测和分析设备和系统的状态&#xff0c;提前发现潜在故障&#xff0c;并采取适当的维修…

制作linux系统内部yum源仓库

需求说明 制作内网linux系统yum源仓库&#xff0c;比较简单的方式就是添加系统镜像&#xff0c;此种yum配置方式可参考文章 https://blog.csdn.net/d1240673769/article/details/108477661 如果无法提供系统镜像&#xff0c;那该如何创建内网的yum源仓库呢&#xff1f;本文提…

互联网Java工程师面试题·Java 总结篇·第六弹

目录 56、TreeMap 和 TreeSet 在排序时如何比较元素&#xff1f;Collections 工具类中的 sort()方法如何比较元素&#xff1f; 57、Thread 类的 sleep()方法和对象的 wait()方法都可以让线程暂停执行&#xff0c;它们有什么区别? 58、线程的 sleep()方法和 yield()方法有什…

在nodejs中实现双重身份验证机制

在nodejs中实现双重身份验证机制 双重身份验证(Two-factor authentication)是一种安全机制&#xff0c;它要求用户提供两种不同的身份验证因素来访问他们的帐户&#xff1a;密码和发送到他们的移动设备的验证码。在本文中&#xff0c;我们将一步步通过使用speakeasy在nodejs中实…

deforum + kandinsky = 视频工作流

像搭积木一样玩AI&#xff0c;随着模型种类的不断丰富&#xff0c;不同的组合会带来什么惊喜&#xff1f;今天和大家分享最近看到的一个视频工作流&#xff08;工具箱&#xff09;。 首先&#xff0c;我们先对deforum和kandinsky做一些基本的介绍&#xff1a; deforum-art/defo…

【论文解读】单目3D目标检测 CUPNet(ICCV 2021)

本文分享单目3D目标检测&#xff0c;CUPNet 模型的论文解读&#xff0c;了解它的设计思路&#xff0c;论文核心观点&#xff0c;模型结构&#xff0c;以及效果和性能。 目录 一、CUPNet简介 二、论文核心观点 三、模型框架 四、损失函数 五、核心观点——3D高度估计误差 引…

Python之并发编程(进程)

文章目录 一、操作系统的发展史二、进程基础(操作系统中的概念)1.什么是进程2.进程的调度算法3.进程的并行与并发4.进程的三状态5.同步异步6.阻塞与非阻塞7.同步异步与阻塞非阻塞综合使用 三、如何创建进程Process的几个方法如何开启多进程进程间的数据默认隔离基于TCP协议的高…

【Qt控件之QButtonGroup】概述及使用

概述 QButtonGroup 类提供了一个容器来组织一组按钮部件。 QButtonGroup 提供了一个抽象容器&#xff0c;可以将按钮部件放置其中。它不提供此容器的可视表示&#xff08;请参见 QGroupBox&#xff0c;用于容器部件&#xff09;&#xff0c;而是管理组中每个按钮的状态。 一个…

Electron webview 内网页 与 preload、 渲染进程、主进程的常规通信 以及企业级开发终极简化通信方式汇总

Electron 嵌入的页面中注入的是 preload.js 通过在标签中给 prelaod赋值&#xff0c;这里提到了 file://前缀&#xff0c;以及静态目录 static 怎么获取 实际代码&#xff0c;其中__static就是我们存放静态文件的地方&#xff0c;这个 static 是 electron 源代码根目录下的文件…

使用unordered_write调优RocksDB写性能

在使用rocksdb存储的服务中&#xff0c;我们发现QPS在4w/s就怎么调整都上不去了&#xff0c;写性能受到了某种限制。为什么呢&#xff1f;下图描述了rocksdb写入的流程。我们发现 unordered_write true可以提高写入吞吐量。 rocksdb的数据正常写入流程是&#xff0c;多个线程形…