Flutter 中的 SkSL 和“Shader Jank Compilation”到底是什么?

Sid*_*ava 1 android lag flutter

问题:

因此,我构建了一个登录屏幕,但该页面的启动时间很糟糕!在查看文档后,我发现了一个名为Shader Jank Complation 的东西,我发现文档令人困惑,但决定实现那里给出的内容。

完成这些步骤后,我运行了该应用程序,性能显着提高。但是,我不知道后台发生了什么以及文档实际指向什么。

我也不明白代码出了什么问题,并且应用程序没有按预期执行或无缘无故地滞后。

代码:

登录屏幕:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:regexed_validator/regexed_validator.dart';

import '../constants/buttons.dart';
import '../constants/colors.dart';
import '../constants/text_style.dart';

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

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {

  String email = "";
  String password = "";

  final formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
        child: SizedBox(
          width: double.infinity,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text(
                "Login",
                textAlign: TextAlign.center,
                style: MyTextStyle.headingTextWelcomeScreen,
              ),
              const SizedBox(
                height: 10,
              ),
              Text(
                "Enter your email and password.",
                textAlign: TextAlign.center,
                style: MyTextStyle.defaultText,
              ),
              const SizedBox(
                height: 30,
              ),
              Form(
                  key: formKey,
                  child: Column(
                    children: [
                      SizedBox(
                        width: MediaQuery.of(context).size.width * 0.7,
                        child: TextFormField(
                          inputFormatters: [
                            FilteringTextInputFormatter.deny(' ')
                          ],
                          keyboardType: TextInputType.emailAddress,
                          cursorColor: MyColors.blue,
                          style: MyTextStyle.defaultBlackText,
                          decoration: InputDecoration(
                            prefixIcon: Icon(
                              Icons.email_outlined,
                              color: MyColors.blue,
                            ),
                            label: Text(
                              "Email",
                              style: MyTextStyle.defaultBlueText,
                            ),
                            enabledBorder: OutlineInputBorder(
                              borderSide: BorderSide(
                                color: MyColors.blue,
                                width: 2,
                              ),
                              borderRadius: const BorderRadius.all(
                                Radius.circular(10),
                              ),
                            ),
                            focusedBorder: OutlineInputBorder(
                              borderSide: BorderSide(
                                color: MyColors.blue,
                                width: 2,
                              ),
                              borderRadius: const BorderRadius.all(
                                Radius.circular(10),
                              ),
                            ),
                          ),
                          onChanged: (value) {
                            email = value;
                          },
                          validator: (value) {
                            if (validator.email(value!)) {
                              return null;
                            } else {
                              return 'Invalid Email';
                            }
                          },
                        ),
                      ),
                      const SizedBox(
                        height: 10,
                      ),
                      SizedBox(
                        width: MediaQuery.of(context).size.width * 0.7,
                        child: TextFormField(
                          inputFormatters: [
                            FilteringTextInputFormatter.deny(' ')
                          ],
                          obscureText: true,
                          keyboardType: TextInputType.visiblePassword,
                          cursorColor: MyColors.blue,
                          style: MyTextStyle.defaultBlackText,
                          decoration: InputDecoration(
                              prefixIcon: Icon(
                                Icons.password_outlined,
                                color: MyColors.blue,
                              ),
                              label: Text("Password",
                                  style: MyTextStyle.defaultBlueText),
                              enabledBorder: OutlineInputBorder(
                                borderSide: BorderSide(
                                  color: MyColors.blue,
                                  width: 2,
                                ),
                                borderRadius: const BorderRadius.all(
                                  Radius.circular(10),
                                ),
                              ),
                              focusedBorder: OutlineInputBorder(
                                borderSide: BorderSide(
                                  color: MyColors.blue,
                                  width: 2,
                                ),
                                borderRadius: const BorderRadius.all(
                                  Radius.circular(10),
                                ),
                              ),
                              errorStyle: MyTextStyle.defaultRedText
                                  .copyWith(fontSize: 12),
                              errorMaxLines: 2),
                          onChanged: (value) {
                            password = value;
                          },
                          validator: (value) {
                            if (validator.password(value!)) {
                              return null;
                            } else {
                              if (password.length < 8) {
                                return 'Invalid Password: Must be grater than 7 characters';
                              } else {
                                return 'Invalid Password: Missing one of the characters @, Captial Letter, Number.';
                              }
                            }
                          },
                        ),
                      ),
                    ],
                  )),
              const SizedBox(
                height: 15,
              ),
              SizedBox(
                height: 45,
                width: MediaQuery.of(context).size.width * 0.7,
                child: DefaultButton(
                  buttonText: "Login",
                  vdc: () {
                    formKey.currentState!.validate();
                  },
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

欢迎屏幕:

import 'package:attendance_management_system_firebase/pages/reg_page.dart';
import 'package:flutter/material.dart';

import '../constants/buttons.dart';
import '../constants/text_style.dart';
import 'login_page.dart';

class WelcomePage extends StatefulWidget {
  static const String id = "welcome_sc";
  const WelcomePage({super.key});

  @override
  State<WelcomePage> createState() => _WelcomePageState();
}

class _WelcomePageState extends State<WelcomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
          child: Center(
        child: Padding(
          padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
          child: SingleChildScrollView(
            child: Column(
              children: [
                Image.asset(
                  "assets/welcome.png",
                  width: MediaQuery.of(context).size.width * 0.65,
                ),
                const SizedBox(
                  height: 35,
                ),
                Text(
                  "Welcome",
                  textAlign: TextAlign.center,
                  style: MyTextStyle.headingTextWelcomeScreen,
                ),
                Text(
                  "Let's get you started with taking attendance!",
                  textAlign: TextAlign.center,
                  style: MyTextStyle.defaultText,
                ),
                const SizedBox(
                  height: 20,
                ),
                SizedBox(
                  height: 45,
                  width: MediaQuery.of(context).size.width * 0.7,
                  child: DefaultButton(
                    buttonText: "Login",
                    vdc: () {
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => const LoginPage()));
                    },
                  ),
                ),
                const SizedBox(
                  height: 5,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      "Don't have an account? ",
                      style: MyTextStyle.defaultBlueText,
                    ),
                    InkWell(
                      onTap: () {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                            builder: (context) => const RegisterPage(),
                          ),
                        );
                      },
                      child: Text(
                        "Register",
                        style: MyTextStyle.defaultBlueText.copyWith(
                            fontWeight: FontWeight.w600,
                            decoration: TextDecoration.underline),
                      ),
                    ),
                  ],
                )
              ],
            ),
          ),
        ),
      )),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

主程序.dart

import 'package:attendance_management_system_firebase/pages/welcome_page.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: WelcomePage(),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

Jus*_*son 6

您的应用程序没有问题。大多数应用程序一开始都会出现着色器编译卡顿的情况。Flutter下的Skia渲染引擎,这个GPU引擎在app第一次打开的时候会生成shaders。

着色器是给予 GPU 在屏幕上绘制 UI 的低级代码。首次启动应用程序时,应用程序中不存在着色器。因此,当应用程序启动时,为了呈现流畅的 UI,** 一帧应在 16 毫秒内渲染。着色器有助于重复执行一系列命令**。将其视为一个组件小部件,我们在高级语言中使用它来清理重复的代码。着色器和小部件的工作方式相似,但着色器是更底层的代码。所以,回到主题,当我们第一次打开应用程序时,Skia有时会在第一次运行应用程序时编译并生成着色器,以尽可能快地使用相同的绘制命令呈现下一帧,而不需要生成帧一次又一次。

着色器的生成需要相当多的时间(大约 200 毫秒或更多,具体取决于情况),这会导致无法在 16 毫秒内渲染的帧卡顿。这种卡顿称为shader-compilation-jank.

Flutter 开发人员正在开发一种名为 的新图形引擎Impeller。这将解决这个问题,但它仍在开发中。因此,为了暂时解决这个问题,我们预编译这些着色器并将它们与应用程序捆绑在一起。

因此,您所做的步骤是当您在配置文件模式下运行应用程序时,skia 生成这些着色器,然后将其保存在文件中。这些着色器预先与应用程序捆绑在一起,这样skia就不必再次编译和生成这些着色器。

希望它是清楚的。