children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(height: 50, width: 50, color: Colors.white),
),
Flexible(
child: Column(
children: const [
Padding(
padding: EdgeInsets.all(8),
child: Text(‘这里是 坚果前端小课堂!’,
style: TextStyle(color: Colors.white)),
),
],
),
),
],
),
);
}
}
Color randomColor() =>
Color((math.Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0);
当您滚动浏览此 UI 并注意该ColorBarState.build
方法的调用方式时,会出现可怕的部分 。每个内部列表包含 100 个元素,因此当 UI 加载时,您会立即看到 100 个“Building ColorBarState”的实例打印到控制台,
更糟糕的是,一旦向下滚动大约一百行,就会再生成一百行。😱😱😱
而且你滑动的快的时候列表会抖动!
要了解如何使您的用户免受卡顿威胁,请等待我的第二节,下一节将使用 Slivers 而不是 ListViews 重建相同的 UI。
===========================================================================
下面的代码构建了与之前相同的 UI,但这次它使用Slivers
而不是收缩包装ListView
对象。本页的其余部分将引导您逐步完成更改。
第1步
首先,将最外面的 ListView 更改为SliverList
.
// Before
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: numberOfLists,
itemBuilder: (context, index) => innerLists[index],
);
}
变成:
// After
@override
Widget build(BuildContext context) {
return CustomScrollView(slivers: innerLists);
}
第2步
其次,将内部列表的类型从List<ListView>
更改为 List<SliverList>
。
// Before
List innerLists = [];
变成:
// After
List innerLists = [];
第 3 步
现在是时候重建内部列表了。的SliverList
类是比原始略有不同ListView
的类,与主要差异是的外观delegate
。
原始版本ListView
对所有内容都使用对象,不知道内部构建器构造函数将被shrinkWrap
.
// Before
@override
void initState() {
super.initState();
for (int i = 0; i < numberOfLists; i++) {
final _innerList = [];
for (int j = 0; j < numberOfItemsPerList; j++) {
_innerList.add(const ColorRow());
}
innerLists.add(
ListView.builder(
itemCount: numberOfItemsPerList,
itemBuilder: (BuildContext context, int index) => _innerList[index],
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
),
);
}
}
更改后,ListView
对象被替换为SliverList
对象,每个对象都使用一个SliverChildBuilderDelegate
来提供高效的按需构建。
// After
@override
void initState() {
super.initState();
for (int i = 0; i < numLists; i++) {
final _innerList = [];
for (int j = 0; j < numberOfItemsPerList; j++) {
_innerList.add(const ColorRow());
}
innerLists.add(
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) => _innerList[index],
childCount: numberOfItemsPerList,
),
),
);
}
}
完整代码:
import ‘package:flutter/material.dart’;
import ‘dart:math’ as math;
void main() {
runApp(SliversApp());
}
class SliversApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: ‘ShrinkWrap vs Slivers’,
home: Scaffold(
appBar: AppBar(
title: const Text(“Revenge of the Slivers”),
),
body: const ShrinkWrapSlivers(),
),
);
}
}
class ShrinkWrapSlivers extends StatefulWidget {
const ShrinkWrapSlivers({
Key? key,
}) : super(key: key);
@override
_ShrinkWrapSliversState createState() => _ShrinkWrapSliversState();
}
class _ShrinkWrapSliversState extends State {
List innerLists = [];
final numLists = 15;
final numberOfItemsPerList = 100;
@override
void initState() {
super.initState();
for (int i = 0; i < numLists; i++) {
final _innerList = [];
for (int j = 0; j < numberOfItemsPerList; j++) {
_innerList.add(const ColorRow());
}
innerLists.add(
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) => _innerList[index],
childCount: numberOfItemsPerList,
),
),
);
}
}
@override
Widget build(BuildContext context) {
return CustomScrollView(slivers: innerLists);
}
}
@immutable
class ColorRow extends StatefulWidget {
const ColorRow({Key? key}) : super(key: key);
@override
State createState() => ColorRowState();
}
class ColorRowState extends State {
Color? color;
@override
void initState() {
super.initState();
color = randomColor();
}
@override
Widget build(BuildContext context) {
print(‘Building ColorRowState’);
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
randomColor(),
randomColor(),
],
),
),
child: Row(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(height: 50, width: 50, color: Colors.white),
),
Flexible(
child: Column(
children: const [
Padding(
padding: EdgeInsets.all(8),
child: Text(‘这里是坚果前端小课堂!’,
style: TextStyle(color: Colors.white)),
),
],
),
),
],
),
);
}
}
Color randomColor() =>
Color((math.Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0);
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。
这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司21年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。
由于篇幅有限,这里以图片的形式给大家展示一小部分。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
后
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。
这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司21年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。
由于篇幅有限,这里以图片的形式给大家展示一小部分。
[外链图片转存中…(img-oGDCU1MI-1712377754582)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。