2021年6月

微软前高管解释了为什么 Windows 10 删除了开机声音

Windows 用户体验团队项目管理前总监 Jensen Harris 在 Youtube 上发布的一段视频解释了为什么从 2010 年开始, Windows 上开始听不到开机声音。

据 Jensen 描述,在 2008 年,他们意识到人们使用电脑已经不同以往,PC 可以在卧室或床上使用,而开机声音在卧室的夜晚显得十分吵闹,可能会吵醒配偶和小孩。

在 Jensen 的视频中,详细的介绍了开机音频的历史,我强烈建议你去看看整个视频,了解一下开机声音的演变历史。

英特尔以一些奇怪的角度嘲讽苹果 M1 芯片

Intel 的首席性能策略师 Ryan Shrout 在最近的一个针对第 11 代 Intel H系列处理器进行推广时,吐槽了 Apple 的M1 芯片。不过,吐槽的点有些无厘头,

Intel 吐槽 macOS 上无法运行一些热门的游戏,但其实此事与 Intel 还是 M1 芯片无关;Intel 还吐槽过去所有的 MacBook Pro 的 PC 都不如 Intel 的第 11 代处理器性能强劲。

Intel 的吐槽看起来颇为无厘头,明明是芯片之争,但吐槽的似乎都是系统。背后可能是 Intel 发现苹果在逃离 Intel 生态后,决定转向支持 PC 市场。

QUIC 协议正式发布了 RFC 9000 ,成为 IETF 标准

QUIC 协议全称为”quick udp internet connection“,快速 UDP 互联网连接,相比于标准的 HTTP2.0 ,他提供了更加安全、可靠和低延时等特性。
QUIC 协议是将过去需要 TCP 协议传递的数据通过由 UDP 传递并添加冗余数据的方式,来确保数据的可靠性,确保服务端所接收到的数据是可靠的。

QUIC 协议发布的 RFC 是互联网基础设施前进的一个重要的里程碑。

了解如何创建 Flutter 应用的界面以及如何在它们之间进行数据传递。

Flutter 是一个流行的开源工具包,它可用于构建跨平台的应用。在文章《用 Flutter 创建移动应用》中,我已经向大家展示了如何在 Linux 中安装 Flutter 并创建你的第一个应用。而这篇文章,我将向你展示如何在你的应用中添加一个列表,点击每一个列表项可以打开一个新的界面。这是移动应用的一种常见设计方法,你可能以前见过的,下面有一个截图,能帮助你对它有一个更直观的了解:

 title=

Flutter 使用 Dart 语言。在下面的一些代码片段中,你会看到以斜杠开头的语句。两个斜杠(//)是指代码注释,用于解释某些代码片段。三个斜杠(///)则表示的是 Dart 的文档注释,用于解释 Dart 类和类的属性,以及其他的一些有用的信息。

查看Flutter应用的主要部分

Flutter 应用的典型入口点是 main() 函数,我们通常可以在文件 lib/main.dart 中找到它:

void main() {
 runApp(MyApp());
}

应用启动时,main() 会被调用,然后执行 MyApp()MyApp 是一个无状态微件(StatelessWidget),它包含了MaterialApp() 微件中所有必要的应用设置(应用的主题、要打开的初始页面等):

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     title: 'Flutter Demo',
     theme: ThemeData(
       primarySwatch: Colors.blue,
       visualDensity: VisualDensity.adaptivePlatformDensity,
     ),
     home: MyHomePage(title: 'Flutter Demo Home Page'),
   );
 }
}

生成的 MyHomePage() 是应用的初始页面,是一个有状态的微件,它包含包含可以传递给微件构造函数参数的变量(从上面的代码看,我们传了一个 title 变量给初始页面的构造函数):

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

有状态微件(StatefulWidget)表示这个微件可以拥有自己的状态:_MyHomePageState。调用 _MyHomePageState 中的 setState() 方法,可以重新构建用户界面:

class _MyHomePageState extends State<MyHomePage> {
 int _counter = 0; // Number of taps on + button.

 void _incrementCounter() { // Increase number of taps and update UI by calling setState().
   setState(() {
     _counter++;
   });
 }
 ...
}

不管是有状态的,还是无状态的微件,它们都有一个 build() 方法,该方法负责微件的 UI 外观。

@override
Widget build(BuildContext context) {
 return Scaffold( // Page widget.
   appBar: AppBar( // Page app bar with title and back button if user can return to previous screen.
     title: Text(widget.title), // Text to display page title.
   ),
   body: Center( // Widget to center child widget.
     child: Column( // Display children widgets in column.
       mainAxisAlignment: MainAxisAlignment.center,
       children: <Widget>[
         Text( // Static text.
           'You have pushed the button this many times:',
         ),
         Text( // Text with our taps number.
           '$_counter', // $ sign allows us to use variables inside a string.
           style: Theme.of(context).textTheme.headline4,// Style of the text, “Theme.of(context)” takes our context and allows us to access our global app theme.
         ),
       ],
     ),
   ),
        // Floating action button to increment _counter number.
   floatingActionButton: FloatingActionButton(
     onPressed: _incrementCounter,
     tooltip: 'Increment',
     child: Icon(Icons.add),
   ),
 );
}

修改你的应用

一个好的做法是,把 main() 方法和其他页面的代码分开放到不同的文件中。要想将它们分开,你需要右击 lib 目录,然后选择 “New > Dart File” 来创建一个 .dart 文件:

 title=

将新建的文件命名为 items_list_page

切换回到 main.dart 文件,将 MyHomePage_MyHomePageState 中的代码,剪切并粘贴到我们新建的文件。然后将光标放到 StatefulWidget 上(下面红色的下划线处), 按 Alt+Enter 后出现下拉列表,然后选择 package:flutter/material.dart

 title=

经过上面的操作我们将 flutter/material.dart 包添加到了 main.dart 文件中,这样我们就可以使用 Flutter 提供的默认的 material 主题微件。

然后, 在类名 MyHomePage 右击,“Refactor > Rename...”将其重命名为 ItemsListPage

 title=

Flutter 识别到你重命名了 StatefulWidget 类,它会自动将它的 State 类也跟着重命名:

 title=

回到 main.dart 文件,将文件名 MyHomePage 改为 ItemsListPage。 一旦你开始输入, 你的 Flutter 集成开发环境(可能是 IntelliJ IDEA 社区版、Android Studio 和 VS Code 或 VSCodium),会给出自动代码补完的建议。

 title=

按回车键即可完成输入,缺失的导入语句会被自动添加到文件的顶部。

 title=

到此,你已经完成了初始设置。现在你需要在 lib 目录创建一个新的 .dart 文件,命名为 item_model。(注意,类命是大写驼峰命名,一般的文件名是下划线分割的命名。)然后粘贴下面的代码到新的文件中:

/// Class that stores list item info:
/// [id] - unique identifier, number.
/// [icon] - icon to display in UI.
/// [title] - text title of the item.
/// [description] - text description of the item.
class ItemModel {
 // class constructor
 ItemModel(this.id, this.icon, this.title, this.description);

 // class fields
 final int id;
 final IconData icon;
 final String title;
 final String description;
}

回到 items_list_page.dart 文件,将已有的 _ItemsListPageState 代码替换为下面的代码:

class _ItemsListPageState extends State<ItemsListPage> {

// Hard-coded list of [ItemModel] to be displayed on our page.
 final List<ItemModel> _items = [
   ItemModel(0, Icons.account_balance, 'Balance', 'Some info'),
   ItemModel(1, Icons.account_balance_wallet, 'Balance wallet', 'Some info'),
   ItemModel(2, Icons.alarm, 'Alarm', 'Some info'),
   ItemModel(3, Icons.my_location, 'My location', 'Some info'),
   ItemModel(4, Icons.laptop, 'Laptop', 'Some info'),
   ItemModel(5, Icons.backup, 'Backup', 'Some info'),
   ItemModel(6, Icons.settings, 'Settings', 'Some info'),
   ItemModel(7, Icons.call, 'Call', 'Some info'),
   ItemModel(8, Icons.restore, 'Restore', 'Some info'),
   ItemModel(9, Icons.camera_alt, 'Camera', 'Some info'),
 ];

 @override
 Widget build(BuildContext context) {
   return Scaffold(
       appBar: AppBar(
         title: Text(widget.title),
       ),
       body: ListView.builder( // Widget which creates [ItemWidget] in scrollable list.
         itemCount: _items.length, // Number of widget to be created.
         itemBuilder: (context, itemIndex) => // Builder function for every item with index.
             ItemWidget(_items[itemIndex], () {
           _onItemTap(context, itemIndex);
         }),
       ));
 }

 // Method which uses BuildContext to push (open) new MaterialPageRoute (representation of the screen in Flutter navigation model) with ItemDetailsPage (StateFullWidget with UI for page) in builder.
 _onItemTap(BuildContext context, int itemIndex) {
   Navigator.of(context).push(MaterialPageRoute(
       builder: (context) => ItemDetailsPage(_items[itemIndex])));
 }
}


// StatelessWidget with UI for our ItemModel-s in ListView.
class ItemWidget extends StatelessWidget {
 const ItemWidget(this.model, this.onItemTap, {Key key}) : super(key: key);

 final ItemModel model;
 final Function onItemTap;

 @override
 Widget build(BuildContext context) {
   return InkWell( // Enables taps for child and add ripple effect when child widget is long pressed.
     onTap: onItemTap,
     child: ListTile( // Useful standard widget for displaying something in ListView.
       leading: Icon(model.icon),
       title: Text(model.title),
     ),
   );
 }
}

为了提高代码的可读性,可以考虑将 ItemWidget 作为一个单独的文件放到 lib 目录中。

现在唯一缺少的是 ItemDetailsPage 类。在 lib 目录中我们创建一个新文件并命名为 item_details_page。然后将下面的代码拷贝进去:

import 'package:flutter/material.dart';

import 'item_model.dart';

/// Widget for displaying detailed info of [ItemModel]
class ItemDetailsPage extends StatefulWidget {
 final ItemModel model;

 const ItemDetailsPage(this.model, {Key key}) : super(key: key);

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

class _ItemDetailsPageState extends State<ItemDetailsPage> {
 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: Text(widget.model.title),
     ),
     body: Center(
       child: Column(
         children: [
           const SizedBox(height: 16),
           Icon(
             widget.model.icon,
             size: 100,
           ),
           const SizedBox(height: 16),
           Text(
             'Item description: ${widget.model.description}',
             style: TextStyle(fontSize: 18),
           )
         ],
       ),
     ),
   );
 }
}

上面的代码几乎没什么新东西,不过要注意的是 _ItemDetailsPageState 里使用了 widget.item.title 这样的语句,它让我们可以从有状态类中引用到其对应的微件(StatefulWidget)。

添加一些动画

现在让我们来添加一些基础的动画:

  1. 找到 ItemWidget 代码块(或者文件)
  2. 将光标放到 build() 方法中的 Icon() 微件上
  3. Alt+Enter,然后选择“Wrap with widget...”

 title=

输入 Hero,然后从建议的下拉列表中选择 Hero((Key key, @required this, tag, this.create))

 title=

下一步, 给 Hero 微件添加 tag 属性 tag: model.id

 title=

最后我们在 item_details_page.dart 文件中做相同的修改:

 title=

前面的步骤,其实我们是用 Hero() 微件对 Icon() 微件进行了封装。还记得吗?前面我们定义 ItemModel 类时,定义了一个 id field,但没有在任何地方使用到。因为 Hero 微件会为其每个子微件添加一个唯一的标签。当 Hero 检测到不同页面(MaterialPageRoute)中存在相同标签的 Hero 时,它会自动在这些不同的页面中应用过渡动画。

可以在安卓模拟器或物理设备上运行我们的应用来测试这个动画。当你打开或者关闭列表项的详情页时,你会看到一个漂亮的图标动画:

 title=

收尾

这篇教程,让你学到了:

  • 一些符合标准的,且能用于自动创建应用的组件。
  • 如何添加多个页面以及在页面间传递数据。
  • 如何给多个页面添加简单的动画。

如果你想了解更多,查看 Flutter 的 文档(有一些视频和样例项目的链接,还有一些创建 Flutter 应用的“秘方”)与 源码,源码的开源许可证是 BSD 3。


via: https://opensource.com/article/20/11/flutter-lists-mobile-app

作者:Vitaly Kuprenko 选题:lujun9972 译者:ywxgod 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

无论你是已经工作了几十年的还是刚开始从业的非工程型技术人,此建议都可以帮助你确定你的位置归属。

 title=

本系列第一篇文章 中 ,我解释了将人员和角色分为“技术”或“非技术”类别的问题。在 第二篇文章 中,我为不写代码的人分享了一些技术岗位角色。这一次,我将把这次探索总结为——“技术或非技术意味着什么”,并提供一些能够在职业发展上帮到你的建议。

无论你是已经从事技术工作数十年,或是刚刚起步,还是正在寻求职业变更,请考虑本文中来自非技术人员但在技术角色方面取得成功的人士的建议。

“不要把你的工作和身份捆绑起来 —— 把它们分开。”

—— Adam Gordon Bell,Earthly Technologies 开发者关系部

转换角色,并不意味着你的技能会消失且你不再具有价值。如果你担任了新角色,则需要专注于该角色的关键技能。培养技能是需要时间的。花点时间,找出新职位的重要技能。

如果你管理工程师们,请鼓励他们提升技术技能的同时发展非工程技能,这些技能往往能比编程能力和技术技能对职业发展和成功产生更显著的变化。

做你自己

“不要让其他人定义你是技术人员还是非技术人员。什么是技术人员,什么不是技术人员,以及这是否重要,是人们必须自己搞清楚的事情。”

—— Adam Gordon Bell

“永远不要用‘我不是技术人员’为开头进行对话。因为很可能让对方产生‘这点我需要提醒你’的想法,这在面试的时候可从来不会留下好印象,而且还有可能会让人觉得你对自己技能缺乏信心。”

—— Mary Thengvall,Camunda 开发者关系总监

避免刻板成见;不是所有的工程师都喜欢《星球大战》或《星际迷航》。不是所有工程师都穿连帽卫衣。工程师也可以和别人交流。

“单单就你的行为举止,旁人就有很多关于技术或非技术方面的看法。在办公室工作的时候,我会穿裙子,因为只有这样我才能舒服一点。”

—— Shailvi Wakhlu,Strava 高级数据总监

了解你的价值

正如我在第一篇文章中讨论的那样,被打上“非技术”的标签会导致 冒充者综合症。承认自己的价值,不要在自己身上贴上“非技术”标签,因为它会限制你的收入潜力和职业发展。

“人们之所以把我重新包装成其他东西,是因为他们认为我和工程师的刻板印象不一样。我很高兴我没有听这些人的话,因为他们本质上是在告诉我,在我拥有的技能之外,去找一份低薪的工作。”

—— Shailvi Wakhlu

“年轻的或者女性技术人,特别是刚接触技术的女性,更容易患上冒名综合症,认为自己技术不够好。比如,‘哦,我只会前端。’,什​​么叫你只会前端?前端也很难的好吧。”

—— Liz Harris

寻找那些可以提升价值并帮到人们的地方

你不需要创建 PR 就可以参与开源。

“当有人想为开源项目做点贡献时,我总是对他说,‘不要想着,得是一个提交才行、得提一个 PR 才可以。’这就好像,‘不行。怎么才能为那个项目贡献点价值呢?’ 如果你没时间提交 PR,那你是不是提个议题并把要点写下来?”

—— Eddie Jaoude,Jaoude Studios 开源程序员

思维的多样性有助于事业成功

看看所有角色和人员的价值和贡献。不要根据头衔将人归到同能力的一组。

“要认识到,所有人(包括自己在内),在任何时候,以及事情全貌的重要性。创造力这个事儿不应该由自我驱动。要知道,对于你所做的事情,你可以做的更好,也可以做的更糟。不要害怕寻求帮助,知道到我们在一起。”

—— Therese Eberhard,电影/广告和视频场景画师

“在我参加过的黑客马拉松中,我们都是技术人员,组建了一支四五个硬核程序员组成的强大团队,但我们输了。我不骗你,我们输了。在新冠疫情之前,我赢了前六次的黑客马拉松,而且当时团队中一半的人属于其他领域的专家。在我们赢过的比赛中,大多数人会认为团队一半人是非技术的,尽管我不喜欢这个术语,因为这像是给团队/项目贴金。我们之所以获胜,是因为我们对所构建的东西有很多不同的看法。”

—— Eddie Jaoude

“我们越能摆脱‘技术/非技术’、‘开发人员/非开发人员’的标签,并理解到一个连续统一的整体存在,我们就越能全力以赴地雇用到合适的人来做这项工作,只要不被你需要‘技术团队’的假设所困扰。”

—— Mary Thengvall

我们的社区和团队越多样化,它们的包容性就越大。

“老实说,无论是从社区角度还是从产品角度,我认为,总的来说,最重要的事情都是,我们应该确保我们建立的是一个包容性的社区,这不仅是为了我们的产品,也不仅是为了我们正在使用的技术,还为了整个人类社会,我想……我敢打赌,如果我们做到了这一点,那么作为人类,我们就比过去更进步了。”

—— Leon Stigter,Lightbend 高级产品经理

如果你以非程序员的技术身份工作,你会给那些认为自己“非技术”的人(或被他人认为是“非技术”的人)提供什么建议? 在评论中分享你的见解。


via: https://opensource.com/article/21/2/advice-non-technical

作者:Dawn Parzych 选题:lujun9972 译者:max27149 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出