百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

将Flutter推向极限:你应该知道的44个性能提示

bigegpt 2024-08-12 14:31 3 浏览

有没有觉得 Flutter 是比赛中的乌龟?别担心!只要我们有几招,我们就能把乌龟变成涡轮增压的兔子。准备好放大了吗?让我们深入了解一些 Flutter 性能技巧!

Flutter 应用程序在默认情况下是高性能的,因此您只需要避免常见的陷阱即可获得出色的性能。如何设计和实现应用的 UI 会对应用的运行效率产生很大影响。

这些最佳实践建议将帮助您编写最高性能的 Flutter 应用程序。

让我们开始阅读吧!!

1.使用 Clean Architecture(干净架构)

Clean Architecture 是一种软件设计模式,强调关注点分离和独立测试。此模式鼓励将应用程序逻辑分离到不同的层中,每一层负责一组特定的任务。Clean Architecture 非常适合大型应用程序,因为它提供了清晰的关注点分离,并使测试更容易。

您可以查看此软件包 - clean_architecture_scaffold

以下是 Flutter 中的一个 Clean Architecture 实现示例:

css复制代码lib/
  data/
    models/
      user_model.dart
    repositories/
      user_repository.dart
  domain/
    entities/
      user.dart
    repositories/
      user_repository_interface.dart
    usecases/
      get_users.dart
  presentation/
    pages/
      users_page.dart
    widgets/
      user_item.dart
    main.dart

2.使用良好的状态管理

状态管理在 Flutter 应用性能中起着至关重要的作用。根据应用的复杂性选择正确的状态管理方法。对于中小型应用程序,内置的 setState 方法可能就足够了。但是,对于更大更复杂的应用程序,可以考虑使用状态管理库,如 bloc 或 riverpod。

dart复制代码// Bad Approach
setState(() {
  // Updating a large data structure unnecessarily
  myList.add(newItem);
});

// Better Approach
final myListBloc = BlocProvider.of<MyListBloc>(context);
myListBloc.add(newItem);

3.使用代码分析工具提高代码质量

代码分析工具,如 Flutter Analyzer 和 Lint,对于提高代码质量和降低 bug 和错误的风险非常有帮助。这些工具可以帮助在潜在问题成为问题之前识别它们,还可以提供改进代码结构和可读性的建议。

以下是在 Flutter 中使用 Flutter Analyzer 的示例:

shell
复制代码flutter analyze lib/

4.使用自动化测试提高代码可靠性

自动化测试是构建大型应用程序的重要组成部分,因为它有助于确保代码可靠并按预期执行。Flutter 为自动化测试提供了几个选项,包括单元测试、小部件测试和集成测试。

下面是使用 Flutter Test 包进行自动化测试的示例:

dart复制代码void main() {
  test('UserRepository returns a list of users', () {
    final userRepository = UserRepository();
    final result = userRepository.getUsers();
    expect(result, isInstanceOf<List<User>>());
  });
}

5.使用 Flutter Inspector 进行调试

Flutter Inspector 是一个强大的工具,用于调试 Flutter 应用程序。它允许开发人员检查和操作小部件树,查看性能指标等。Flutter Inspector 可以通过 Flutter DevTools 浏览器扩展或通过命令行访问。

下面是使用 Flutter Inspector 进行调试的示例:

shell
复制代码flutter run --debug

6.延迟加载和分页

一次获取和呈现大量数据会显著影响性能。实现延迟加载和分页以根据需要加载数据,特别是对于长列表或数据密集型视图。

dart复制代码// Bad Approach
// Fetch and load all items at once.
List<Item> allItems = fetchAllItems();

// Better Approach
// Implement lazy loading and pagination.
List<Item> loadItems(int pageNumber) {
  // Fetch and return data for the specific page number.
}

// Use a ListView builder with lazy loading.
ListView.builder(
  itemCount: totalPages,
  itemBuilder: (context, index) {
    return FutureBuilder(
      future: loadItems(index),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          // Build your list item here.
        } else {
          return CircularProgressIndicator();
        }
      },
    );
  },
);

7.缩小图像大小

大型图像文件可能会降低应用的性能,尤其是在加载多个图像时。压缩和调整图像大小,以减少其文件大小,而不会影响太多的质量。

示例:假设您有一个高分辨率的图像,但您只需要将其显示在应用程序中的较小容器中。您可以使用 flutter_image_compress 库来调整其大小,而不是使用原始的高分辨率图像。

dart复制代码import 'package:flutter_image_compress/flutter_image_compress.dart';

// Original image file
var imageFile = File('path/to/original/image.png');
// Get the image data
var imageBytes = await imageFile.readAsBytes();
// Resize and compress the image
var compressedBytes = await FlutterImageCompress.compressWithList(
  imageBytes,
  minHeight: 200,
  minWidth: 200,
  quality: 85,
);
// Save the compressed image to a new file
var compressedImageFile = File('path/to/compressed/image.png');
await compressedImageFile.writeAsBytes(compressedBytes);

8.优化动画

避免使用可能影响应用性能的繁重或复杂的动画,尤其是在较旧的设备上。明智地使用动画,并考虑使用 Flutter 的内置动画,如 AnimatedContainerAnimatedOpacity 等。

dart复制代码// Bad Approach
// Using an expensive animation
AnimatedContainer(
  duration: Duration(seconds: 1),
  height: _isExpanded ? 300 : 1000,
  color: Colors.blue,
);
// Better Approach
// Using a simple and efficient animation
AnimatedContainer(
  duration: Duration(milliseconds: 500),
  height: _isExpanded ? 300 : 100,
  color: Colors.blue,
);

9.优化应用程序启动时间

通过优化初始化过程减少应用的启动时间。使用 flutter_native_splash 包在应用加载时显示闪屏,并将非必要组件的初始化延迟到应用启动后。

10.避免使用深树,而是创建一个单独的小部件

你不想继续滚动你的 IDE 与一千行代码。尝试创建一个单独的小部件。它将看起来干净,易于重构。

dart复制代码//Bad
Column(
  children: [
    Container(
      //some lengthy code here
    ),
    Container(
      //some another lengthy code
    ),
    //some another lengthy code
  ],
)

//Good
Column(
  children: [
    FirstLengthyCodeWidget(),
    SecondLengthyCodeWidget(),
    //another lengthy code widget etc
  ],
)

11.使用级联(..)

如果你刚开始使用 flutter,你可能还没有使用这个操作符,但是当你想在同一个对象上执行一些任务时,它非常有用。

dart复制代码//Bad
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;

//Good
var paint = Paint()
  ..color = Colors.black
  ..strokeCap = StrokeCap.round
  ..strokeWidth = 5.0;

12.使用展开运算符(...)

这是 dart 提供的另一个漂亮的操作符。您可以简单地使用此操作符执行许多任务,例如 if-else、加入列表等。

dart复制代码//Bad
@override
Widget build(BuildContext context) {
  bool isTrue = true;
  return Scaffold(
    body: Column(
      children: [
        isTrue ? const Text('One') : Container(),
        isTrue ? const Text('Two') : Container(),
        isTrue ? const Text('Three') : Container(),
      ],
    ),
  );
}

//Good
@override
Widget build(BuildContext context) {
  bool isTrue = true;
  return Scaffold(
    body: Column(
      children: [
        if(isTrue)...[
          const Text('One'),
          const Text('Two'),
          const Text('Three')
        ]
      ],
    ),
  );
}

13.避免使用硬编码的样式、装饰等

如果您在应用程序中使用硬编码的样式、装饰等,并且稍后决定更改这些样式。你会一个接一个地修复它们。

dart复制代码//Bad
Column(
  children: const [
    Text(
      'One',
      style: TextStyle(
        fontSize: 14,
        fontWeight: FontWeight.normal,
      ),
    ),
    Text(
      'Two',
      style: TextStyle(
        fontSize: 14,
        fontWeight: FontWeight.normal,
      ),
    ),
  ],
)

//Good
Column(
  children: [
    Text(
      'One',
      style: Theme.of(context).textTheme.subtitle1,
    ),
    Text(
      'Two',
      style: Theme.of(context).textTheme.subtitle1,
    ),
  ],
),

14.小心使用 build()

避免使用过大的单个小部件和较大的 build() 函数。根据封装以及它们的变化方式将它们拆分为不同的小部件。

当在 State 对象上调用 setState() 时,所有派生小部件都会重新生成。因此,将 setState() 调用本地化到 UI 实际需要更改的子树部分。如果更改只包含在树的一小部分中,请避免在树的较高位置调用 setState()

让我们看看这个例子,我们希望当用户按下图标时,只有这个图标的颜色会改变。

因此,如果我们在一个小部件中拥有所有这些 UI,当按下图标时,它将更新整个 UI。我们可以做的是将图标分隔为 StatefulWidget

之前

dart复制代码import 'package:flutter/material.dart';

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

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

class _FidgetWidgetState extends State<FidgetWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('App Title'),
      ),
      body: Column(
        children: [
          Text('Some Text'),
          IconButton(
            onPressed: () => setState(() {
              // Some state change here
            }),
            icon: Icon(Icons.favorite),
          ),
        ],
      ),
    );
  }
}

之后

dart复制代码import 'package:flutter/material.dart';

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

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

class _MyIconWidgetState extends State<MyIconWidget> {
  @override
  Widget build(BuildContext context) {
    return IconButton(
      onPressed: () => setState(() {

      }),
      icon: Icon(Icons.favorite),
    );
  }
}

15.使用 Widgets 而不是函数

您可以节省 CPU 周期,并与构造函数一起使用,在需要时进行重建,还有更多好处(重复使用等......)。

dart复制代码//Bad
@override
Widget build(BuildContext context) {
  return Column(
    children: [
      _getHeader(),
      _getSubHeader(),
      _getContent()
    ]
   );
}

//Good
@override
Widget build(BuildContext context) {
  return Column(
    children: [
      HeaderWidget(),
      SubHeaderWidget(),
      ContentWidget()
    ]
  );
}

正如 Riverpod、Provider 和其他软件包的创建者 Remi Rousselet 所说。“类有更好的默认行为。使用方法的唯一好处就是可以少写一点代码。没有任何功能上的好处”。

16.尽可能使用 final

使用 final 关键字可以大大提高应用的性能。当一个值被声明为 final 时,它只能被设置一次,此后不会改变。这意味着框架不需要经常检查更改,从而提高了性能。

dart
复制代码final items = ["Item 1", "Item 2", "Item 3"];

在这个例子中,变量项被声明为 final ,这意味着它的值不能被改变。这提高了性能,因为框架不需要检查此变量的更改。

17.尽可能使用 const

dart复制代码x = Container();
y = Container();
x == y // false

x = const Container();
y = const Container();
x == y // true

const widget 在编译时创建,因此在运行时速度更快。

18.尽可能使用 const 构造函数

dart复制代码class CustomWidget extends StatelessWidget {
  const CustomWidget();

  @override
  Widget build(BuildContext context) {
    ...
  }
}

当构建自己的小部件或使用 Flutter 小部件时。这有助于 Flutter 只重建应该更新的小部件。

19.尽可能使用私有变量/方法

除非必要,否则尽可能使用 private 关键字。

dart复制代码//Bad
class Student {
  String name;
  String address;
  Student({
      required this.name,
      required this.address,
    });
  }
}

//Good
class Student{
  String _name;
  String _address;
  Student({
    required String name,
    required String address,
  }):
  _name = name,
  _address = address;
}

是的,与性能相比,它更像是 Dart 的最佳实践。但是,最佳实践可以在某种程度上提高性能,比如理解代码、降低复杂性等。

20.使用 nil 代替 const Container()

dart复制代码// good
text != null ? Text(text) : const Container()
// Better
text != null ? Text(text) : const SizedBox()
// BEST
text != null ? Text(text) : nil
or
if (text != null) Text(text)

它只是一个基本的元素小部件,几乎没有成本。查看包 - nil。

21.在 ListView 中对长列表使用 itemExtent

这有助于 Flutter 计算 ListView 滚动位置,而不是计算每个小部件的高度,并使滚动动画更具性能。

默认情况下,每个孩子都必须确定其范围,这在性能方面是相当昂贵的。显式设置该值可以节省大量 CPU 周期。列表越长,使用此属性获得的速度就越快。

dart复制代码//Nope
final List<int> _listItems = <int>[1, 2, 3, 4, 5, 6, 7, 8, 9];

@override
Widget build(BuildContext context) {
  return ListView.builder(
    itemCount: _listItems.length,
    itemBuilder: (context, index) {
      var item = _listItems[index];
      return Center(
        child: Text(item.toString())
      );
    }
}

//Good
final List<int> _listItems = <int>[1, 2, 3, 4, 5, 6, 7, 8, 9];

@override
Widget build(BuildContext context) {
  return ListView.builder(
    itemExtent: 150,
    itemCount: _listItems.length,
    itemBuilder: (context, index) {
      var item = _listItems[index];
      return Center(
        child: Text(item.toString())
      );
    }
}

22.避免将 AnimationController 与 setState 一起使用

这不仅会导致重新构建整个 UI 的动画部件,而且会使动画滞后。

dart复制代码void initState() {
  _controller = AnimationController(
    vsync: this,
    duration: Duration(seconds: 1),
  )..addListener(() => setState(() {}));
}

Column(
  children: [
    Placeholder(), // rebuilds
    Placeholder(), // rebuilds
    Placeholder(), // rebuilds
    Transform.translate( // rebuilds
      offset: Offset(100 * _controller.value, 0),
      child: Placeholder(),
    ),
  ],
),

dart复制代码void initState() {
  _controller = AnimationController(
    vsync: this,
    duration: Duration(seconds: 1),
  );
  // No addListener(...)
}

AnimatedBuilder(
  animation: _controller,
  builder: (_, child) {
  return Transform.translate(
    offset: Offset(100 * _controller.value, 0),
    child: child,
    );
  },
  child: Placeholder(),
),

23.使用 Keys 加速 Flutter 性能

使用 Keys 时,Flutter 能更好地识别小部件。这让我们的性能提高了 4 倍。

dart复制代码// FROM
return value ? const SizedBox() : const Placeholder(),
// TO
return value ? const SizedBox(key: ValueKey('SizedBox')) : const Placeholder(key: ValueKey('Placeholder')),
----------------------------------------------
// FROM
final inner = SizedBox();
return value ? SizedBox(child: inner) : inner,
// TO
final global = GlobalKey();
final inner = SizedBox(key: global);
return value ? SizedBox(child: inner) : inner,

谨慎: ValueKey 会让你的代码看起来有点臃肿 GlobalKey 有点危险,但有时候值得。

24.使用图像 ListView 时优化内存

dart复制代码ListView.builder(
  ...
  addAutomaticKeepAlives: false (true by default)
  addRepaintBoundaries: false (true by default)
);

ListView 无法杀死屏幕上不可见的子代。如果子代具有高分辨率图像,就会消耗大量内存。

通过将这些选项设置为 false,可能会导致使用更多的 GPU 和 CPU 工作,但它可以解决我们的内存问题,并且您将获得非常高性能的视图,而不会出现明显的问题。

25.使用 for/while 代替 foreach/map

如果你要处理大量的数据,使用正确的循环可能会影响你的性能。

26.预缓存您的图像和图标

这取决于具体情况,但我一般会在主系统中预先缓存所有图像。

对于图片

你不需要任何包装,只要用-

dart复制代码precacheImage(
  AssetImage(imagePath),
  context
);

对于 SVG

您需要 flutter_svg

dart复制代码precachePicture(
  ExactAssetPicture(SvgPicture.svgStringDecoderBuilder, iconPath),
  context
);

27.使用 SKSL 预热

shell复制代码flutter run --profile --cache-sksl --purge-persistent-cache
flutter build apk --cache-sksl --purge-persistent-cache

如果一个应用程序在第一次运行时有不稳定的动画,然后在相同的动画中变得平滑,那么它很可能是由于着色器编译的不稳定。

28.考虑使用 RepaintBoundary

此小部件为其子小部件创建单独的显示列表,这可以提高特定情况下的性能。

29.如果可能,请使用生成器命名的构造函数

dart
复制代码Listview.builder()

生成器只会在屏幕上渲染显示的项目。即使看不到,也能显示所有的孩子。

30.不要使用 ShrinkWrap 任何可滚动的小部件

测量内容问题。

31.使用重载函数时使用 ISOLATE (隔离)

有些方法非常昂贵,比如图像处理,它们可能会让应用程序在主线程中冻结。如果不想出现这种情况,就应该考虑使用隔离。

32.不要为每一件小事使用隔离

但如果您在任何地方都使用隔离区,即使是最小的操作,您的应用程序也会变得非常笨拙。因为生成隔离区的操作并不便宜。这需要时间和资源。

33.正确处理数据

不必要的内存使用会悄无声息地杀死应用程序内部的数据。因此,不要忘记处理数据。

34.压缩数据以节省内存

dart复制代码final response = await rootBundle.loadString('assets/en_us.json');

final original = utf8.encode(response);

final compressed = gzip.encode(original);
final decompress = gzip.decode(compressed);

final enUS = utf8.decode(decompress);

这样还可以节省一些内存。

35.保持更新 Flutter

每一个版本的 Flutter 都会变得越来越快。因此,不要忘了及时更新您的 Flutter 版本,让您的作品更加精彩。

36.在真实的设备上测试性能

始终在真实的设备(包括较旧型号)上测试应用的性能,以确定在模拟器或较新设备上可能不明显的任何性能问题。

37.首选 StatelessWidget 优于 StatefulWidget

StatelessWidgetStatefulWidget 更快,因为顾名思义,它不需要管理状态。这就是为什么如果可能的话,你应该选择它的原因。

选择 StatefulWidget 时...

你需要一个准备功能 initState()

您需要使用 dispose() 处理资源

您需要使用 setState() 触发小部件重建

你的小部件有变化的变量(非 final)

在所有其他情况下,您应该首选 StatelessWidget

38.不使用 OpacityWidget

当与动画一起使用时, Opacity 小部件可能会导致性能问题,因为 Opacity 小部件的所有子小部件也将在每个新帧中重建。在这种情况下,最好使用 AnimatedOpacity 。如果要淡入图像,请使用 FadeInImage 小部件。如果您希望有一个不透明度的颜色,请绘制一个不透明度的颜色。

dart复制代码//Bad
Opacity(opacity: 0.5, child: Container(color: Colors.red))
//Good
Container(color: Color.fromRGBO(255, 0, 0, 0.5))

39.首选 SizedBox 而不是 Container

Container widget 非常灵活。例如,您可以自定义填充或边框,而无需将其嵌套在另一个小部件中。但如果你只需要一个具有一定高度和宽度的盒子,最好使用 SizedBox 小部件。它可以成为常量,而 Container 不能。

要在 Row/Column, 中添加空白,请使用 SizedBox 而不是 Container

dart复制代码//NOPE
@override
Widget build(BuildContext context) {
  return Column(
    children: [
      Text(header),
      Container(height: 10),
      Text(subheader),
      Text(content)
    ]
  );
}

//YES~
@override
Widget build(BuildContext context) {
return Column(
  children: [
      Text(header),
      const SizedBox(height: 10),
      Text(subheader),
      Text(content)
    ]
  );
}

40.不要使用剪裁

剪裁是一个非常昂贵的操作,当你的应用变慢时应该避免。如果将剪切行为设置为 Clip.antiAliasWithSaveLayer,则代价会更高。试着寻找其他的方法来实现你的目标。例如,一个圆角边框的矩形可以用 borderRadius 属性来代替剪裁。

41.使用 Offstage 小部件

Offstage 小部件允许您隐藏一个小部件,而无需将其从小部件树中移除。这对于提高性能非常有用,因为框架不需要重建隐藏的小部件。

dart复制代码Offstage(
  offstage: !showWidget,
  child: MyWidget(),
)

在本例中,当 showWidget 变量为假时, Offstage 小部件用于隐藏 MyWidget 小部件。这通过减少需要重建的小部件的数量来提高性能。

你有没有想过 OffstageOpacityVisibility widget 之间的区别?在这里你可以找到简短的解释。

在 Flutter 中, Offstage widget 用于在布局中隐藏子 widget,同时它仍然是树的一部分。它可用于有条件地显示或隐藏子部件,而无需重新构建整个树。

Opacity widget 用于控制子 widget 的透明度。它采用一个介于 0.0 和 1.0 之间的值,其中 0.0 表示完全透明,1.0 表示完全不透明。但是,重要的是要注意它可能会影响性能,因此仅在必要时使用它。

Visibility 小部件用于控制子小部件的可见性。它可以用于有条件地显示或隐藏子部件,而不必重新构建整个树。

这三个部件都用于控制子部件的显示,但它们的控制方式不同。Offstage 控制布局,Opacity 控制透明度,Visibility 控制可见性

42.使用 WidgetsBinding.instance.addPostFrameCallback

在某些情况下,我们需要在渲染帧后执行某些操作。既不要尝试使用任何延迟函数,也不要创建自定义回调!我们可以使用 WidgetsBinding.instance.addPostFrameCallback 方法来做到这一点。该回调将在框架渲染后调用,并通过避免不必要的重建来提高性能。

dart复制代码WidgetsBinding.instance.addPostFrameCallback((_) {
 //Perform the action here
});

43.使用 AutomaticKeepAliveClientMixin

当使用 ListViewGridView 时,可以多次构建子对象。为了避免这种情况,我们可以对子部件使用 AutomaticKeepAliveClientMixin 。这将使子部件的状态保持活跃并提高性能。

dart复制代码class MyChildWidget extends StatefulWidget {
  @override
  _MyChildWidgetState createState() => _MyChildWidgetState();
}

class _MyChildWidgetState extends State<MyChildWidget> with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    return Text("I am a child widget");
  }
}

在本例中, MyChildWidget 类使用 AutomaticKeepAliveClientMixin mixin, wantKeepAlive 属性设置为 true 。这将使 MyChildWidget 的状态保持活动状态,并防止它被多次重建,从而提高性能。

44.使用 MediaQuery.sizeOf(context)

当您使用 MediaQuery.of(context).size 时,flutter 会将您的小部件与 MediaQuery 的大小相关联,这在代码库中多次使用时可能会导致不必要的重建。通过使用 MediaQuery.sizeOf(context) ,您可以绕过这些不必要的重建,并增强应用的响应能力。也适用于其他 MediaQuery 方法,例如使用 .platformBrightnessOf(context) 而不是 .of(context).

好吧,但是如何测量它们呢?

要衡量 Dart/Flutter 应用程序的性能,可以使用性能视图。它提供了显示 Flutter 帧和时间线事件的图表。

不要在调试模式下测量性能

有一种用于性能和内存测量的特殊模式,即 Profile 模式。您可以通过 Android Studio 或 Visual Studio Code 等 IDE 或执行以下 CLI 命令来运行它:

shell
复制代码flutter run - profile

在调试模式下,应用程序未被优化,因此通常比其他模式运行得慢。

不要在模拟器中测量性能

运行编译后的应用程序检查性能问题时,请勿使用模拟器。模拟器无法像真实设备一样再现真实世界的行为。在实际设备上运行时,您可能会发现一些并非真正的问题。模拟器也不支持配置文件模式。

结论部分

优化 Flutter 应用的性能对于提供无缝用户体验至关重要。通过实施这些提示,您可以进一步优化 Flutter 应用的性能。请记住,性能优化是一个持续的过程,定期的性能分析和测试对于确保您的应用保持其高性能标准至关重要。


原文:medium.com/@panuj330/p…

作者:独立开发者张张 链接:https://juejin.cn/post/7283827523002859576 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


相关推荐

为3D手游打造, Visual Studio Unity扩展下载

IT之家(www.ithome.com):为3D手游打造,VisualStudioUnity扩展下载7月30日消息,微软正式发布升级版VisualStudioToolsforUnity扩...

由ArcMap属性字段自增引出字段计算器使用Python的技巧

1.前言前些日子有人问我ArcMap中要让某个字段的值实现自增有什么方法?我首先想到像SQLServer中对于数值型字段可以设置自增。所以我打开ArcCatalog查看发现只提供默认值,没办法只能看...

微软首次回答 HoloLens 相关问题,终于爆料了

fengo2015/04/2115:11注:本文作者张静是NVIDIAGPU架构师,微信公众号“黑客与画家”(HackerAndPainter),知乎专栏地址。欢迎各位童鞋与他交流探讨。...

C#指针的应用(c#指针类型)

C#在有限的范围内支持指针。C#的指针只不过是一个持有另一类型内存地址的变量。但是在C#中,指针只能被声明为持有值类型和数组的内存地址。与引用类型不同,指针类型不被默认的垃圾收集机制所跟踪。出于同...

C# 堆栈(Stack)(c# 堆栈中定位调用messagebox 的地方)

C#集合在C#中,堆栈(Stack)是一种后进先出(LIFO,LastInFirstOut)的数据结构。堆栈(Stack)适用于存储和按顺序处理数据,其中最新添加的元素会最先被移除。堆...

欢迎回来:Fortran意外重回流行编程语言20强榜单

TIOBE指数是用来确定一种编程语言受欢迎程度的指标之一。它并不表明哪种编程语言是最好的,也不表明哪种编程语言写的代码行数最多,而是利用在谷歌、维基百科、必应、亚马逊、YouTube等各种引擎和网站上...

C#+NET MAUI实现跨平台/终端(linux,win,ios等)解决方案

简介.NETMulti-platformAppUI(.NETMAUI)是一个跨平台的框架,用于使用C#和XAML创建移动和桌面应用程序。使用.NETMAUI,您可以用一套代码库开发可以在A...

C#代码安全红线:SQL注入防护终极方案,让你的系统固若金汤

在数字化时代,应用系统的安全性至关重要。而SQL注入攻击,长期盘踞在OWASP(OpenWebApplicationSecurityProject)漏洞榜单的前列,成为众多基于数据库的应用系统...

C# (一)状态机模式(状态机代码实现)

最近空闲,炒炒隔夜饭,以前这些模式在自己项目种应用过不少,但一直没有像别人那样写一个系列,最近年纪大了,很多东西都忘记了,特别AI的兴起,更少写代码了,反正没什么事情,自己在重写一遍吧。创建型模式(5...

C# 中 Predicate 详解(c#中的replace)

Predicate泛型委托:表示定义一组条件并确定指定对象是否符合这些条件的方法。此委托由Array和List类的几种方法使用,用于在集合中搜索元素。Predicate<T>...

C#中$的用法?(c#中&&什么意思)

文章来自AI问答。在C#中,$符号用于字符串插值(StringInterpolation)。字符串插值是C#6.0引入的一种特性,它允许你在字符串中直接嵌入表达式,而不需要使用string.For...

C#并行编程:Parallel类(c# 并行处理)

在Parallel类中提供了三个静态方法作为结构化并行的基本形式:Parallel.Invoke方法:并行执行一组委托。Parallel.For方法:执行与C#for循环等价的并行方法。Parall...

颠覆认知!用Span重构foreach循环竟让数据处理快如闪电

在C#编程的世界里,数据处理效率始终是开发者们关注的焦点。随着项目规模的扩大和数据量的激增,哪怕是细微的性能提升,都可能对整个应用的响应速度和用户体验产生深远影响。近年来,C#引入的Span<T...

Unity3D手游开发实践《腾讯桌球》客户端开发经验总结

本次分享总结,起源于腾讯桌球项目,但是不仅仅限于项目本身。虽然基于Unity3D,很多东西同样适用于Cocos。本文从以下10大点进行阐述:1.架构设计2.原生插件/平台交互3.版本与补丁4.用脚本,...

.NET 7 AOT 的使用以及 .NET 与 Go 互相调用

目录背景C#部分环境要求创建一个控制台项目体验AOT编译C#调用库函数减少体积C#导出函数C#调用C#生成的AOTGolang部分安装GCCGolang导出函数.NETC#...