当前位置: 首页 > article >正文

Flutter路由

路由作为一种页面切换的能力,非常重要。Flutter 中路由管理有几个重要的点。

Navigator 1.0:Flutter 早期路由系统,侧重于移动端 ,命令式编程风格,使用 Navigator.push() 和 Navigator.pop() 等方法来管理路由栈。

Navigator 2.0:Flutter1.22 版本以后新增,侧重于桌面端/网页端,声明式编程风格,使用 Router 和 RouteInformationParser 等类来描述和管理路由树。

Flutter路由重要的类

1.Route:应用程序页面的抽象, Navigator 管理 Route。

2.Navigator:负责路由管理的重要类,通过 push 和 pop 进行页面跳转。

Flutter 跳转方式

动态路由

适于单次导航的场景,直接在代码中创建和导航的路由。

Navigator.push(context,
    MaterialPageRoute(builder: (context) => RouterPageA()));

   Navigator.pop(context);
import 'package:flutter/material.dart';

import 'dart_test_router1.dart';

class TestRouterPage extends StatelessWidget {
  const TestRouterPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Test Navigator"),
      ),
      body: Container(
        alignment: Alignment.center,
        margin: const EdgeInsets.all(10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text("Test MaterialPageRoute"),
            ElevatedButton(
              onPressed: () {
                Navigator.push(context,
                    MaterialPageRoute(builder: (context) => RouterPageA()));
              },
              child: Text("Click ElevatedButton"),
              style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.blue,
                  foregroundColor: Colors.white,
                  elevation: 10,
                  minimumSize: Size(double.infinity, 50),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10))),
            )
          ],
        ),
      ),
    );
  }
}
import 'package:flutter/material.dart';

class RouterPageA extends StatelessWidget {
  const RouterPageA({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("RouterPageA"),
      ),
      body: Container(
        alignment: Alignment.center,
        margin: const EdgeInsets.all(10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text("Test Navigator.pop"),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: Text("Click ElevatedButton"),
              style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.blue,
                  foregroundColor: Colors.white,
                  elevation: 10,
                  minimumSize: Size(double.infinity, 50),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10))),
            )
          ],
        ),
      ),
    );
  }
}

Navigator.push有两个参数,一个是BuildContext,另一个是Route。代码中使用的是MaterialPageRoute,执行与对应平台风格一致的切换动画(android 与 ios平台不同)。如果使用 CupertinoPageRoute,页面切换效果是左右滑动。

PageRoute可以自定义,实现自定义页面切换的动画和行为。如果想自定义下过渡动画,使用 PageRouteBuilder 创建自定义路由,通过 pageBuilder 和 transitionsBuilder 属性来定义页面和过渡动画。

通过 pageBuilder 实现页面渐入动画

                Navigator.of(context).push(PageRouteBuilder(
                    pageBuilder: (context, animation, secondaryAnimation) {
                  return FadeTransition(
                      opacity: animation, child: const RouterPageA());
                }));

pageBuilder + transitionsBuilder 实现过渡动画


                Navigator.of(context).push(PageRouteBuilder(
                    pageBuilder: (context, animation, secondaryAnimation) =>
                        const RouterPageA(),
                    transitionsBuilder:
                        (context, animation, secondaryAnimation, child) {
                     //动画的起始位置,轴y方向屏幕下侧偏移起点
                      var start = const Offset(0, 1);
                     //动画的结束位置,0表示没有偏移
                      var end = Offset.zero;
                      //动画曲线,easeInOut 表示开始慢,中间加速,结束慢
                      var curve = Curves.easeInOut;
                      // 创建一个从begin到end的补间动画,.chain 表示与曲线结合
                      var tween = Tween(begin: start, end: end)
                          .chain(CurveTween(curve: curve));
                       // SlideTransition 是一个动画Widget
                      return SlideTransition(
                          position: animation.drive(tween), child: child);
                    }));

 静态路由

静态路由需要提前注册,首先给每个路由定义一个名称,通过这个名称来导航到对应的路由。

在应用根级别 (MaterialApp 或者 CupertinoApp ) 中定义路由,使用routes参数将路由名称映射到对应的Widget。

不带参数与返回值案例

Navigator.of(context).pushNamed("/dart_test_router1");
import 'package:flutter/material.dart';

import 'dart_test_router1.dart';

class TestStaticRouterPage extends StatelessWidget {
  const TestStaticRouterPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Test Router Demo",
      theme: ThemeData(
        useMaterial3: false,
        primarySwatch: Colors.blue,
        textButtonTheme: const TextButtonThemeData(
          
          style: ButtonStyle(splashFactory: NoSplash.splashFactory),
        ),
      ),
      home: const RealTestStaticRouterPage(),
      routes: {
      //  "/": (context) => const RealTestStaticRouterPage(),
        "/dart_test_router1": (context) => const RouterPageA()
      },
     // initialRoute: "/",
    );
  }
}

class RealTestStaticRouterPage extends StatelessWidget {
  const RealTestStaticRouterPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("TEST STATIC ROUTER PAGE"),
      ),
      body: Container(
        alignment: Alignment.center,
        margin: const EdgeInsets.all(10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text("Test Static Router Page"),
            ElevatedButton(
              onPressed: () {
                Navigator.of(context).pushNamed("/dart_test_router1");
              },
              child: Text("Click ElevatedButton"),
              style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.blue,
                  foregroundColor: Colors.white,
                  elevation: 10,
                  minimumSize: Size(double.infinity, 50),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10))),
            )
          ],
        ),
      ),
    );
  }

带参数与返回值

import 'package:flutter/material.dart';

import 'dart_test_router1.dart';
import 'dart_test_router3.dart';

class TestStaticRouterPage extends StatelessWidget {
  const TestStaticRouterPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Test Router Demo",
      theme: ThemeData(
        useMaterial3: false,
        primarySwatch: Colors.blue,
        textButtonTheme: const TextButtonThemeData(
          // 鍘绘帀 TextButton 鐨勬按娉㈢汗鏁堟灉
          style: ButtonStyle(splashFactory: NoSplash.splashFactory),
        ),
      ),
      home: const RealTestStaticRouterPage(),
      routes: {
        //  "/": (context) => const RealTestStaticRouterPage(),
        "/dart_test_router1": (context) => const RouterPageA(),
        "/dart_test_router3": (context) => const RouterPage3()
      },
      // initialRoute: "/",
    );
  }
}

class RealTestStaticRouterPage extends StatelessWidget {
  const RealTestStaticRouterPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("TEST STATIC ROUTER PAGE"),
      ),
      body: Container(
        alignment: Alignment.center,
        margin: const EdgeInsets.all(10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text("Test Static Router Page"),
            ElevatedButton(
              onPressed: () async {
                var result = await Navigator.of(context).pushNamed(
                    "/dart_test_router3",
                    arguments: {"title": "Hello"});
                print(result);
              },
              child: Text("Click ElevatedButton"),
              style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.blue,
                  foregroundColor: Colors.white,
                  elevation: 10,
                  minimumSize: Size(double.infinity, 50),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10))),
            )
          ],
        ),
      ),
    );
  }
import 'package:flutter/material.dart';

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

  @override
  State<StatefulWidget> createState() {
    return _RouterPage3State();
  }
}

class _RouterPage3State extends State<RouterPage3> {
  @override
  Widget build(BuildContext context) {
    var args =
        ModalRoute.of(context)?.settings.arguments as Map<String, dynamic>?;
    final title = args?['title'] ?? "DEFAULT TITLE";

    return Scaffold(
      appBar: AppBar(
        title: Text("RouterPageA"),
      ),
      body: Container(
        alignment: Alignment.center,
        margin: const EdgeInsets.all(10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text("GET TITLE===========銆?title"),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context, "I went from RouterPage3");
              },
              child: Text("Click ElevatedButton"),
              style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.blue,
                  foregroundColor: Colors.white,
                  elevation: 10,
                  minimumSize: Size(double.infinity, 50),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10))),
            )
          ],
        ),
      ),
    );
  }
}

 

2024-09-12 10:01:46.569 25438-25629 flutter  I  I went from RouterPage3

路由操作

路由替换

像登录页跳首页的场景,我们希望页面跳转成功后,回到上上个页面。我们可以通过pushReplacement、pushReplacementNamed实现。

API一:动态路由替换

Navigator.of(context).pushReplacement(
                    MaterialPageRoute(builder: (context) => RouterPageA()));

API二:静态路由替换

         var result = await Navigator.of(context).pushReplacementNamed(
                    "/dart_test_router3",
                    arguments: {"title": "Hello"});

新路由入栈+移除之前的路由,直到条件满足

pushAndRemoveUntil 将给定路由推送给Navigator,删除先前的路由,直到该函数的参数predicate返回true为才停止。

import 'package:flutter/material.dart';

import 'dart_test_router1.dart';
import 'dart_test_router3.dart';

class TestRouterPage4 extends StatelessWidget {
  const TestRouterPage4({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Test pushAndRemoveUntil",
      theme: ThemeData(
          useMaterial3: false,
          primarySwatch: Colors.blue,
          textButtonTheme: const TextButtonThemeData(
            style: ButtonStyle(splashFactory: NoSplash.splashFactory),
          )),
      home: const RealTestRouterPage4(),
    );
  }
}

class RealTestRouterPage4 extends StatelessWidget {
  const RealTestRouterPage4({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Test pushAndRemoveUntil"),
      ),
      body: Container(
        alignment: Alignment.center,
        margin: const EdgeInsets.all(10),
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text("test pushAndRemoveUntil"),
              ElevatedButton(
                onPressed: () {
                  Navigator.pushAndRemoveUntil(
                      context,
                      MaterialPageRoute(builder: (context) => RouterPageA()),
                      (Route<dynamic> route) => route.isFirst);
                },
                child: Text("Click ElevatedButton"),
                style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.blue,
                    foregroundColor: Colors.white,
                    elevation: 10,
                    minimumSize: Size(double.infinity, 50),
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10))),
              )
            ]),
      ),
    );
  }
}

这个方式是跳转到某个页面,然后移除路由直到...为止

路由出栈,直到条件满足

在flutter 路由跳转中,我们想要回到特定的一个页面 比如:从 A -> B-> C ->D,我们向从 D页面 pop至 B 页面。我们可以使用 popUtil方法回到 B 页面。

popUntil 反复执行pop 直到该函数的参数predicate返回true为止。

import 'package:flutter/material.dart';

import 'dart_test_router6.dart';

class TestRouterPage5 extends StatelessWidget {
  const TestRouterPage5({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Test popUntil TestRouterPage5",
      theme: ThemeData(
          useMaterial3: false,
          primarySwatch: Colors.blue,
          textButtonTheme: const TextButtonThemeData(
            style: ButtonStyle(splashFactory: NoSplash.splashFactory),
          )),
      home: const RealTestRouterPage5(),
    );
  }
}

class RealTestRouterPage5 extends StatelessWidget {
  const RealTestRouterPage5({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Test popUntil TestRouterPage5"),
      ),
      body: Container(
        alignment: Alignment.center,
        margin: const EdgeInsets.all(10),
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text("test popUntil TestRouterPage5"),
              ElevatedButton(
                onPressed: () {
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => TestRouterPage6()));
                },
                child: Text("Click ElevatedButton"),
                style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.blue,
                    foregroundColor: Colors.white,
                    elevation: 10,
                    minimumSize: Size(double.infinity, 50),
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10))),
              )
            ]),
      ),
    );
  }
}
import 'package:flutter/material.dart';

import 'dart_test_router7.dart';

class TestRouterPage6 extends StatelessWidget {
  const TestRouterPage6({super.key});

  @override
  Widget build(BuildContext context) {
    return RealTestRouterPage6();
  }
}

class RealTestRouterPage6 extends StatelessWidget {
  const RealTestRouterPage6({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Test popUntil TestRouterPage6"),
      ),
      body: Container(
        alignment: Alignment.center,
        margin: const EdgeInsets.all(10),
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text("test popUntil TestRouterPage6"),
              ElevatedButton(
                onPressed: () {
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => TestRouterPage7()));
                },
                child: Text("Click ElevatedButton"),
                style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.blue,
                    foregroundColor: Colors.white,
                    elevation: 10,
                    minimumSize: Size(double.infinity, 50),
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10))),
              )
            ]),
      ),
    );
  }
}
import 'package:flutter/material.dart';

class TestRouterPage7 extends StatelessWidget {
  const TestRouterPage7({super.key});

  @override
  Widget build(BuildContext context) {
    return RealTestRouterPage7();
  }
}

class RealTestRouterPage7 extends StatelessWidget {
  const RealTestRouterPage7({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Test popUntil TestRouterPage7"),
      ),
      body: Container(
        alignment: Alignment.center,
        margin: const EdgeInsets.all(10),
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text("test popUntil TestRouterPage7"),
              ElevatedButton(
                onPressed: () {
                  Navigator.of(context)
                      .popUntil((Route<dynamic> route) => route.isFirst);
                },
                child: Text("Click ElevatedButton"),
                style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.blue,
                    foregroundColor: Colors.white,
                    elevation: 10,
                    minimumSize: Size(double.infinity, 50),
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10))),
              )
            ]),
      ),
    );
  }
}

上面的代码中调用Navigator.of(context)
                      .popUntil((Route<dynamic> route) => route.isFirst);直接回到了 TestRouterPage5。

 

删除指定路由

获得当前路由

ModalRoute.of(context);

 移除指定路由


if (route != null) {
  Navigator.of(context).removeRoute(route);
}

移除指定路由下方的单个路由

if (route != null) {
  Navigator.of(context).removeRouteBelow(route);
}

页面传参与数据回传

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:gsy_flutter_demo/widget/dart_test_router2.dart';

import 'dart_test_router1.dart';

class TestRouterPage extends StatelessWidget {
  const TestRouterPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Test Navigator"),
      ),
      body: Container(
        alignment: Alignment.center,
        margin: const EdgeInsets.all(10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text("Test MaterialPageRoute"),
            ElevatedButton(
              onPressed: () async {
                String backContent = await Navigator.of(context).push(MaterialPageRoute(
                    builder: (context) => RouterPage2(title: "Custom Title")));
                print(backContent);
              },
              child: Text("Click ElevatedButton"),
              style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.blue,
                  foregroundColor: Colors.white,
                  elevation: 10,
                  minimumSize: Size(double.infinity, 50),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10))),
            )
          ],
        ),
      ),
    );
  }
}
import 'package:flutter/material.dart';

class RouterPage2 extends StatefulWidget {
  final String title;

  const RouterPage2({super.key, required this.title});

  @override
  State<StatefulWidget> createState() {
    return _RouterPage2State();
  }
}

class _RouterPage2State extends State<RouterPage2> {
  @override
  Widget build(BuildContext context) {
    var widgitTitle = widget.title;

    return Scaffold(
      appBar: AppBar(
        title: Text("RouterPageA"),
      ),
      body: Container(
        alignment: Alignment.center,
        margin: const EdgeInsets.all(10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text("GET TITLE===========銆?widgitTitle"),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context, "I went from RouterPageA");
              },
              child: Text("Click ElevatedButton"),
              style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.blue,
                  foregroundColor: Colors.white,
                  elevation: 10,
                  minimumSize: Size(double.infinity, 50),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10))),
            )
          ],
        ),
      ),
    );
  }
}

2024-09-11 14:51:16.211 24765-24840 flutter I  I went from RouterPageA


 

Navigator  的工作流程

Navigator  的核心是对路由栈的管理。当你调用 Navigator.push 时,一个新的路由被创建并推入栈顶;当你调用 Navigator.pop 时,栈顶的路由被移除。

  const Navigator({
    super.key,
    this.pages = const <Page<dynamic>>[],
    this.onPopPage,
    this.initialRoute,
    this.onGenerateInitialRoutes = Navigator.defaultGenerateInitialRoutes,
    this.onGenerateRoute,
    this.onUnknownRoute,
    this.transitionDelegate = const DefaultTransitionDelegate<dynamic>(),
    this.reportsRouteUpdateToEngine = false,
    this.clipBehavior = Clip.hardEdge,
    this.observers = const <NavigatorObserver>[],
    this.requestFocus = true,
    this.restorationScopeId,
    this.routeTraversalEdgeBehavior = kDefaultRouteTraversalEdgeBehavior,
  });

Navigator.push 

#Navigator.push

  @optionalTypeArgs
  static Future<T?> push<T extends Object?>(BuildContext context, Route<T> route) {
    return Navigator.of(context).push(route);
  }

Navigator.push 调用Navigator.of(context).push(route),内部 调用NavigatorState 的 push 方法:

  @optionalTypeArgs
  Future<T?> push<T extends Object?>(Route<T> route) {
    _pushEntry(_RouteEntry(route, pageBased: false, initialState: _RouteLifecycle.push));
    return route.popped;
  }

 #NavigatorState

  void _pushEntry(_RouteEntry entry) {
    assert(!_debugLocked);
    assert(() {
      _debugLocked = true;
      return true;
    }());
    assert(entry.route._navigator == null);
    assert(entry.currentState == _RouteLifecycle.push);
    _history.add(entry);
    _flushHistoryUpdates();
    assert(() {
      _debugLocked = false;
      return true;
    }());
    _afterNavigation(entry.route);
  }

这里发生了一系列操作:

  • _history.add(route) : 将 新路由 添加到 路由栈 中。
  • route.install() : 安装路由,将页面挂载到 widget 树上。
  • route.didPush() : 通知 路由 已经被推入 栈顶 。
  • _cancelActivePointers() : 取消所有正在进行的触摸事件,防止发生意外事件。
  • route.didChange() : 通知 路由 状态发生变化。

push 方法返回一个 Future,该 Future 会在路由完成push操作时完成。

Navigator.pop

#Navigator.pop 

 Navigator.of(context).pop();
  @optionalTypeArgs
  void pop<T extends Object?>([ T? result ]) {
    assert(!_debugLocked);
    assert(() {
      _debugLocked = true;
      return true;
    }());
    final _RouteEntry entry = _history.lastWhere(_RouteEntry.isPresentPredicate);
    if (entry.pageBased) {
      if (widget.onPopPage!(entry.route, result) && entry.currentState == _RouteLifecycle.idle) {
        // The entry may have been disposed if the pop finishes synchronously.
        assert(entry.route._popCompleter.isCompleted);
        entry.currentState = _RouteLifecycle.pop;
      }
      entry.route.onPopInvoked(true);
    } else {
      entry.pop<T>(result);
      assert (entry.currentState == _RouteLifecycle.pop);
    }
    if (entry.currentState == _RouteLifecycle.pop) {
      _flushHistoryUpdates(rearrangeOverlay: false);
    }
    assert(entry.currentState == _RouteLifecycle.idle || entry.route._popCompleter.isCompleted);
    assert(() {
      _debugLocked = false;
      return true;
    }());
    _afterNavigation(entry.route);
  }
  • history.lastWhere:找到最后一个处于 “存在”状态 的路由条目。
  • entry.pageBased:路由是否是基于页面的。
  • widget.onPopPage:执行页面pop操作。
  • entry.route.onPopInvoked(true):通知路由pop操作被调用。
  • entry.pop<T>(result):直接调用pop。
  • _afterNavigation(entry.route):导航完成后回调。


http://www.kler.cn/a/320199.html

相关文章:

  • wordpress独立站首页调用产品的三种方法
  • Dart:字符串
  • LeetCode:1. 两数之和
  • uni-app快速入门(十)--常用内置组件(下)
  • Unity 编辑器下 Android 平台 Addressable 加载模型粉红色,类似材质丢失
  • Nginx Spring boot指定域名跨域设置
  • react crash course 2024(3) jsx语法及组件
  • mysql数据库:超键、候选键、主键与外键
  • 百度营销转化追踪(网页JS布码)
  • [Oracle] ORA-04036: 实例使用的 PGA 内存超出 PGA_AGGREGATE_LIMIT
  • [AIGC实战]5分钟使用EAS一键部署MLLM多模态大语言模型应用
  • 如何去编写一个好的单元测试,通义灵码是如何快速生成单元测试?
  • 免费的高质量、美观的甘特图模板
  • 求二叉树的高度(递归和非递归)
  • 【排序算法】选择排序、堆排序
  • 【数据结构之线性表】有序表的合并(链表篇)
  • 论文笔记:基于共注意网络的多模态假新闻检测
  • 基于组网分割的超大规模设计 FPGA 原型验证解决方案
  • power bi制作各季度收入累加柱状图——日期表、calculate、datesytd
  • Windows内核编程基础(2)
  • Ubuntu 20.04安装CMake 3.1
  • go fiber 证书
  • C语言 | Leetcode C语言题解之第437题路径总和III
  • 深度学习:神经网络--手写数字识别
  • RocketMQ消息重试机制解析!
  • 优化java中 HashMap 的容量](capacity值)