2024年Android最新Flutter 命令本质之 Flutter tools 机制源码深入分析,2024年最新阿里面试java

建议

当我们出去找工作,或者准备找工作的时候,我们一定要想,我面试的目标是什么,我自己的技术栈有哪些,近期能掌握的有哪些,我的哪些短板 ,列出来,有计划的去完成,别看前两天掘金一些大佬在驳来驳去 ,他们的观点是他们的,不要因为他们的观点,膨胀了自己,影响自己的学习节奏。基础很大程度决定你自己技术层次的厚度,你再熟练框架也好,也会比你便宜的,性价比高的替代,很现实的问题但也要有危机意识,当我们年级大了,有哪些亮点,与比我们经历更旺盛的年轻小工程师,竞争。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!!!!!!!

  • 准备想说怎么样写简历,想象算了,我觉得,技术就是你最好的简历

  • 我希望每一个努力生活的it工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

  • 有什么问题想交流,欢迎给我私信,欢迎评论

【附】相关架构及资料

Android高级技术大纲

面试资料整理

内含往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

}

//2、步骤1中runner.run的第二个核心参数方法定义

//FlutterCommand为packages/flutter_tools/lib/src/runner/flutter_command.dart中定义的抽象类

//这个方法本质就是把flutter执行的命令参数列表全部加入列表,类似命令模式

List generateCommands({

@required bool verboseHelp,

@required bool verbose,

}) => [

AnalyzeCommand(

),

AssembleCommand(verboseHelp: verboseHelp, buildSystem: globals.buildSystem),

AttachCommand(verboseHelp: verboseHelp),

BuildCommand(verboseHelp: verboseHelp),

ChannelCommand(verboseHelp: verboseHelp),

CleanCommand(verbose: verbose),

ConfigCommand(verboseHelp: verboseHelp),

CreateCommand(verboseHelp: verboseHelp),

DaemonCommand(hidden: !verboseHelp),

DevicesCommand(verboseHelp: verboseHelp),

DoctorCommand(verbose: verbose),

DowngradeCommand(verboseHelp: verboseHelp),

DriveCommand(verboseHelp: verboseHelp,

),

EmulatorsCommand(),

FormatCommand(),

GenerateCommand(),

GenerateLocalizationsCommand(

),

InstallCommand(),

LogsCommand(),

MakeHostAppEditableCommand(),

PackagesCommand(),

PrecacheCommand(

),

RunCommand(verboseHelp: verboseHelp),

ScreenshotCommand(),

ShellCompletionCommand(),

TestCommand(verboseHelp: verboseHelp),

UpgradeCommand(verboseHelp: verboseHelp),

SymbolizeCommand(

),

// Development-only commands. These are always hidden,

IdeConfigCommand(),

UpdatePackagesCommand(),

];

让我们把目光先移动到runner.dart文件的 run 方法,然后回过头来看上面代码中的步骤1如何调用步骤2,如下:

Future run(

List args,

List Function() commands, {

bool muteCommandLogging = false,

bool verbose = false,

bool verboseHelp = false,

bool reportCrashes,

String flutterVersion,

Map<Type, Generator> overrides,

}) async {

//1、FlutterCommandRunner位于packages/flutter_tools/lib/src/runner/flutter_command_runner.dart

return runInContext(() async {

reportCrashes ??= !await globals.isRunningOnBot;

//2、创建runner对象实例,并把上一片段代码中步骤2方法返回的FlutterCommand列表追加进runner中

final FlutterCommandRunner runner = FlutterCommandRunner(verboseHelp: verboseHelp);

commands().forEach(runner.addCommand);

return runZoned<Future>(() async {

try {

//3、依据args参数执行runner实例的run方法

await runner.run(args);

} catch (error, stackTrace) { // ignore: avoid_catches_without_on_clauses

}

}, onError: (Object error, StackTrace stackTrace) async { // ignore: deprecated_member_use

});

}, overrides: overrides);

}

可以看到,首先实例化了一个 FlutterCommandRunner 对象,接着把所有支持的 FlutterCommand 列表加入 runner 对象中,然后调用了 runner 的 run 方法,所以我们现在查看packages/flutter_tools/lib/src/runner/flutter_command_runner.dart文件的 run 方法,如下:

@override

Future run(Iterable args) {

//本质调用了父类CommandRunner的run方法,run方法调用了子类FlutterCommandRunner的runCommand方法

//子类FlutterCommandRunner的runCommand最终又调用了父类CommandRunner的runCommand方法

return super.run(args);

}

所以我们接下来看父类 CommandRunner 的 runCommand 方法,如下:

Future<T?> runCommand(ArgResults topLevelResults) async {

//1、flutter命令后面传递进来参数,譬如build apk

var argResults = topLevelResults;

//2、前面分析过的,runner中添加的支持命令列表

var commands = _commands;

//3、定义一个Command变量,用来最终依据参数赋值为对应的Command对象实例

Command? command;

var commandString = executableName;

//4、while条件为真,因为commands为支持的参数列表

while (commands.isNotEmpty) {

//5、填充指令

argResults = argResults.command!;

command = commands[argResults.name]!;

command._globalResults = topLevelResults;

command._argResults = argResults;

commands = command._subcommands as Map<String, Command>;

commandString += ’ ${argResults.name}';

}

//6、执行对应命令的run方法

return (await command.run()) as T?;

}

}

可以看到,这就是一个标准的命令模式设计,先把支持的命令添加到列表,然后依据参数遍历匹配对应命令进行执行。下面我们以flutter build apk命令为例来看其对应的 BuildCommand 命令(packages/flutter_tools/lib/src/commands/build.dart)实现,如下:

class BuildCommand extends FlutterCommand {

BuildCommand({ bool verboseHelp = false }) {

addSubcommand(BuildAarCommand(verboseHelp: verboseHelp));

addSubcommand(BuildApkCommand(verboseHelp: verboseHelp));

addSubcommand(BuildAppBundleCommand(verboseHelp: verboseHelp));

addSubcommand(BuildIOSCommand(verboseHelp: verboseHelp));

addSubcommand(BuildIOSFrameworkCommand(

buildSystem: globals.buildSystem,

verboseHelp: verboseHelp,

));

addSubcommand(BuildIOSArchiveCommand(verboseHelp: verboseHelp));

addSubcommand(BuildBundleCommand(verboseHelp: verboseHelp));

addSubcommand(BuildWebCommand(verboseHelp: verboseHelp));

addSubcommand(BuildMacosCommand(verboseHelp: verboseHelp));

addSubcommand(BuildLinuxCommand(

operatingSystemUtils: globals.os,

verboseHelp: verboseHelp

));

addSubcommand(BuildWindowsCommand(verboseHelp: verboseHelp));

addSubcommand(BuildWindowsUwpCommand(verboseHelp: verboseHelp));

addSubcommand(BuildFuchsiaCommand(verboseHelp: verboseHelp));

}

//上一小段代码中command = commands[argResults.name]就是这么得到的

//name=build就是执行flutter build apk中的build字符串

@override

final String name = ‘build’;

@override

final String description = ‘Build an executable app or install bundle.’;

@override

Future runCommand() async => null;

}

可以看到,任意一个命令基本都继承自 FlutterCommand 实现,命令的执行都是调用了 FlutterCommand 的 run 方法,如下:

abstract class FlutterCommand extends Command {

//runner对象中最终执行调用的方法是这个

@override

Future run() {

return context.run(

name: ‘command’,

overrides: <Type, Generator>{FlutterCommand: () => this},

body: () async {

try {

//见名知意,先校验再运行命令

commandResult = await verifyThenRunCommand(commandPath);

} finally {

}

},

);

}

@mustCallSuper

Future verifyThenRunCommand(String commandPath) async {

//1、如果需要更新缓存就先更新缓存

if (shouldUpdateCache) {

await globals.cache.updateAll({DevelopmentArtifact.universal});

await globals.cache.updateAll(await requiredArtifacts);

}

globals.cache.releaseLock();

//2、校验命令

await validateCommand();

//3、如果需要先执行pub就先执行,譬如pub get下载依赖

if (shouldRunPub) {

//4、执行pub get下载依赖,即下载pubspec.yaml里配置的依赖

await pub.get(

context: PubContext.getVerifyContext(name),

generateSyntheticPackage: project.manifest.generateSyntheticPackage,

checkUpToDate: cachePubGet,

);

await project.regeneratePlatformSpecificTooling();

if (reportNullSafety) {

await _sendNullSafetyAnalyticsEvents(project);

}

}

setupApplicationPackages();

//5、真正开始执行命令

return runCommand();

}

}

绕一圈最终我们又回到 BuildCommand 类,可以发现其 runCommand 方法重写为空实现,而其构造时通过 addSubcommand 方法追加了很多子命令,譬如执行flutter build aar编译 aar 的 BuildAarCommand 命令、执行flutter build apk编译 apk 的 BuildApkCommand 命令。整个 sub command 与其宿主又算是一个责任链,所以上面同样的套路顺序对于 sub command 同样适用,因此我们去看下编译 apk 产物的 BuildApkCommand 源码(packages/flutter_tools/lib/src/commands/build_apk.dart),如下:

class BuildApkCommand extends BuildSubCommand {

BuildApkCommand({bool verboseHelp = false}) {

//一堆参数的确认

}

//对应flutter build apk里面子命令字符串apk

@override

final String name = ‘apk’;

//本质命令执行方法

@override

Future runCommand() async {

//调用androidBuilder的buildApk方法进行真正的编译,目测里面的产物也就是上一篇文章分析的那些

//androidBuilder位于packages/flutter_tools/lib/src/android/android_builder.dart

await androidBuilder.buildApk(

project: FlutterProject.current(),

target: targetFile,

androidBuildInfo: androidBuildInfo,

);

return FlutterCommandResult.success();

}

}

顺着这条路我们继续跟进位于packages/flutter_tools/lib/src/android/android_builder.dart的 androidBuilder 属性的 buildApk 方法,如下:

//本质是packages/flutter_tools/lib/src/context_runner.dart中context.run方法中的AndroidGradleBuilder实例

AndroidBuilder get androidBuilder {

return context.get();

}

//抽象类定义,AndroidBuilder

abstract class AndroidBuilder {

const AndroidBuilder();

// 定义编译aar的方法

Future buildAar({

@required FlutterProject project,

@required Set androidBuildInfo,

@required String target,

@required String outputDirectoryPath,

@required String buildNumber,

});

结尾

最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

高级UI,自定义View

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

[外链图片转存中…(img-RD2q2bOW-1715666011871)]

高级UI,自定义View

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

[外链图片转存中…(img-5cQ3CpHG-1715666011872)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 30
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值