移动端App 页面秒开优化总结

news2025/2/25 15:38:53

前言

App优化,是一个工作、面试或KPI都绕不开的话题,如何让用户使用流畅呢?今天谨以此篇文章总结一下过去两个月我在工作中的优化事项到底有那些,优化方面还算小白,有不对的地方还望指出海涵, 该文章主要通过讲述Native跳转到Flutter界面秒开率提升

问题分析

当你拿到反馈App页面渲染时间长的工单的时候,第一步想到的不应该是有那些那些方法可以降低耗时,我们应该根据自己的真实业务触发,第一步 验证 通过打点或者工具去验证这个问题,了解 一个页面打开耗时的统计方式分析一个打开耗时是由那些方面组成,通过那些技术手段去解决80%的问题,抓大放小去处理问题。

通过工具分析启动链路耗时,发现部分必要接口RT时间较长,Flutter引擎冷启耗时较长和View渲染耗时为主要耗时项。接下来就围绕着三个大方面去做一些优化。

网络优化

以Android 界面跳转链路来说 ,具体链路看下图(模拟数据 主要明白思想)

看到串行,就知道这里肯定可以有文章做

可以看到在网络请求可以提前到 Router环节去解析并进行预加载,并行的话可以优化 必要接口RT的时长,节省的时间在页面秒开链路中占比最多。

在这里需要兼容网络返回较慢的情况,我们可以引入骨架图,提升上屏率。

数据预请求

Router和请求

通过拦截路由地址,判断路径是否属于预请求白名单。如果匹配,进入预请求逻辑,发起网络拼接和请求,在获取到结果进行本地缓存,供消费界面去消费。因为考虑到网络返回如果慢与界面,可以提供回调,消费界面进来进行绑定。

端侧通讯

由于Native 跳转到 Flutter ,所以这里需要借助 Channel来进行管道传递,这里我们没有使用MethodChannel 而是选择 可以Native主动通知Flutter 的EventChannel来接收消息。

public class EventChannelManager implements IFlutterProphetPlugin {
    private static Map<String, EventChannel.EventSink> cachedEventSinkMap = new HashMap<>();
    private static LinkedList<Object> dataList = new LinkedList<>();

    public final static String CHANNEL_REQUEST_PRE = "event_channel";

    private static EventChannelManager instance;

    public static EventChannelManager getInstance() {
        if (null == instance) {
            instance = new EventChannelManager();
        }
        return instance;
    }

    @Creator
    public static IFlutterProphetPlugin create() {
        return new EventChannelManager();
    }

    //初始化
    @Override
    public void initChannel(FlutterEngine engine) {
        try {
            EventChannel eventChannel_pre = new EventChannel(engine.getDartExecutor(), CHANNEL_REQUEST_PRE);
            eventChannel_pre.setStreamHandler(new ProphetStreamHandler(CHANNEL_REQUEST_PRE));
        } catch (Exception ex) {
            Log.e(TAG, "init channel err :" + ex.getMessage());
        }
    }

    //发送消息
    @Override
    public void sendEventToStream(String eventChannel, Object data) {
        synchronized (this) {
            try {
                EventChannel.EventSink eventSink = cachedEventSinkMap.get(eventChannel);
                if (null != eventSink) {
                    eventSink.success(data);
                } else {
                    dataList.add(data);
                }
            } catch (Exception ex) {
            }
        }
    }

    //关闭
    public void cancel(String eventChannel) {
        EventChannel.EventSink eventSink = cachedEventSinkMap.get(eventChannel);
        if (null != eventSink) {
            eventSink.endOfStream();
        }
    }

    public static class ProphetStreamHandler implements EventChannel.StreamHandler {
        private String eventChannel;

        public ProphetStreamHandler(String eventChannel) {
            this.eventChannel = eventChannel;
        }

        @Override
        public void onListen(Object arguments, EventChannel.EventSink events) {
            cachedEventSinkMap.put(eventChannel, events);
            if (dataList.size() != 0) {
                for (Object obj : dataList) {
                    events.success(obj);
                }
                dataList.clear();
            }
        }

        @Override
        public void onCancel(Object arguments) {
            cachedEventSinkMap.remove(eventChannel);
        }
    }

}

上述代码为通用EventChannel创建和发送消息工具类,接口不贴了…

缓存

预请求模块中,如果网络请求结果成功,可以将结果写入缓存SDK中(可以根据缓存SDK策略,内存和磁盘缓存都做好处理)。结合缓存策略,再次进入界面即可先读取缓存数据上屏,通过顶部Load状态提醒用户 预请求的数据正在加载中,来缩短秒开时间。

端智能

通过大数据和算法对用户习惯性的使用链路进行分析,判断用户下一个节点将会进入哪个界面,匹配到预请求白名单,也可以更早的进行预请求逻辑 (没有集团SDK支撑的话可以不列为主要优化方式)。

数据后带

以自己维护的App来说,首屏商品列表会返回很多数据包括但不限于:商品Url、商品名称、价格等核心信息,在进入商品详情中,我们通常会把商品id发送到详情界面,并再次进行商品详情接口的请求,那么我们可以通过数据后带的方式,先让详情页核心数据显示出来,然后通过局部骨架图来等待详情信息的返回,感官上缩短界面等待时长。

数据延后

首屏中还会有很多二级弹窗列表数据接口的请求,其实这里的接口可以通过延后的方式来加载并渲染出来,减少首屏刚开始的CPU使用,为核心View渲染让步,减少CPU竞争。

业务逻辑优化

部分不重要接口除了可以延后处理外,还可以通过推动后端合理缩小数据结构,减少不必要的网络消耗产生。对于部分小量接口,可以通过搭车的方式 进行接口合并 一块返回,部分数据可能不需要实时更新的,可以减少不必要请求来进行优化。

布局优化

异步加载

假设场景是搜索结果列表,我们可以在数据请求前置的同时,去异步 inflate 一些 recyclerview 的 itemview,渲染阶段就可以节约 createViewHolder 的时间。(这里只是进行一个场景举例,更多的使用方法和业务强耦合,需要自行分析和合理设计避免负向优化)

递进加载

顾名思义,其实递进加载和数据延后请求原理相似,每个界面可能都会有重要View,以商品列表为例,我可能更希望商品列表数据先返回回来,其他的接口可以延后,提升界面渲染速度。


为了帮助到更好的了解学习到移动端的性能优化相关的知识点,下面针对 性能优化和Flutter 知识点进行整理,大家可以进行参考《性能优化学习手册》 与《Flutter 学习手册》

###《性能优化学习手册》:https://0a.fit/dNHYY
启动优化、UI布局优化、卡顿优化、布局优化、崩溃优化、网路优化、大图加载优化、存储优化、APK瘦身优化等……

###《Flutter 学习手册》:https://0a.fit/xvcHV

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/156117.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSS入门三、盒子模型

零、文章目录 文章地址 个人博客-CSDN地址&#xff1a;https://blog.csdn.net/liyou123456789个人博客-GiteePages&#xff1a;https://bluecusliyou.gitee.io/techlearn 代码仓库地址 Gitee&#xff1a;https://gitee.com/bluecusliyou/TechLearnGithub&#xff1a;https:…

力扣sql基础篇(四)

力扣sql基础篇(四) 1 每位学生的最高成绩 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # rank()函数间隔排序 若前两个字段值相同且都是并列的第一名,那么后面的一个非连续数字就是第三名 如 1 1 3 SELECT e.student_id,e.course_id,e.grade FROM…

ISO12233分辨率测试卡分类及功能说明

概述相机图像分辨率的测试&#xff0c;依据的标准是ISO 12233. 目前分为 ISO12233:2000 ,ISO12233:4000, ISO12233:2014.目前很多厂家已经开始使用新的ISO标准&#xff0c;淘汰了十几年前的“落伍”标准&#xff0c;而更新成了ISO12233&#xff1a;2014。新的分辨率测试标板是由…

代码随想录算法训练营第四期第五十六天 | 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇

583. 两个字符串的删除操作 # 给定两个单词word1和word2&#xff0c;返回使得word1和word2相同所需的最小步数。 # 每步可以删除任意一个字符串中的一个字符。 # # 示例 1&#xff1a; # 输入: word1 "sea", word2 "eat" # 输出: 2 # 解释: 第一步将 &…

安顺控股冲刺A股上市:拟募资6.5亿元,九成收入来自天然气销售

近日&#xff0c;安顺控股股份有限公司&#xff08;下称“安顺控股”&#xff09;递交招股书&#xff0c;准备在上海证券交易所主板上市。本次冲刺上市&#xff0c;安顺控股计划募资6.50亿元&#xff0c;将用于溧阳市城镇燃气高压管网二期项目、溧阳市美丽乡村天然气利用项目一…

openstack私有网络

1.前情回顾 目前环境使用的是Provider网络现在需要将其修改为Self-service网络&#xff0c;类似于公有云的vpc网络 2.流程 1.控制节点配置修改 1.修改/etc/neutron/neutron.conf的[DEFAULT]区域 # 原来的配置 # core_plugin ml2 # service_plugins # # 修改后的配置 c…

GitHub Enterprise Server 存在授权不当漏洞(CVE-2022-46258)

漏洞描述 GitHub Enterprise Server 是一个面向开源及私有软件项目的托管平台&#xff0c;GitHub scope 用于限制 OAuth token 的访问范围。 在 GitHub Enterprise Server 中&#xff0c;除非提交位于同一存储库的不同分支中且和 Workflow files 内容相同的 Workflow 文件 &a…

【学习】Reptile、梯度下降的LSTM、Siamese Network、原型网络、匹配网络、关系网络

文章目录ReptileRNNLSTM梯度下降的LSTM基于度量的方法Siamese NetworkN-way Few/One-shot Learning原型网络匹配网络关系网络虚拟数据的少量学习Train Test as RNNReptile RNN LSTM RNN的变形 加入门 梯度下降的LSTM GD看似像简化的LSTM 可以让机器自动学习这些zf和zi …

sql的where使用运算后的列后报错

sql的where语句中如果使用了经过运算处理后的某个列的话会报错&#xff0c;例如&#xff1a;上面红框部分就是经过运算后的列&#xff0c;但这个语法是错误的&#xff0c;但如果想通过运算后的某个列来筛选条件&#xff0c;应该怎么办&#xff1f;可以使用嵌套查询&#xff1a;…

SpringBoot实践(三十八):自定义spring-boot-starter

目录 自动配置原理 自定义starter包 导入springboot的自动配置依赖 测试业务代码 spring.factories配置 ​编辑 本地包上传 使用自定义starter依赖 测试和配置 自动配置原理 基于springBoot的starter机制能够让我们在使用外部包时候非常方便&#xff0c;只需要引入该组…

PCB学习笔记—3D PCB封装的创建

放置3D元件体&#xff1a;常规的、自定义、圆柱形、球体。第一个是厚度&#xff0c;第二个是焊盘和芯片的悬浮高度。一般电阻的高度设置成0.6mm就够了&#xff0c;电容1.25mm&#xff0c;悬浮高度为0。按键&#xff1a;放置3D元件体&#xff0c;Tab键&#xff0c;选择常规&…

快过年静不下心?不如刷刷《剑指offer》静一静(第七天)

跟着博主一起刷题 这里使用的是题库&#xff1a; https://leetcode.cn/problem-list/xb9nqhhg/?page1 目录剑指 Offer 49. 丑数剑指 Offer 51. 数组中的逆序对剑指 Offer 55 - I. 二叉树的深度剑指 Offer 49. 丑数 剑指 Offer 49. 丑数 我一开始的思路是&#xff0c;把数字1~无…

机器学习HW15元学习

文章目录一、简介Task: Few-shot Classification实验1、simple2、medium3、strong4、boss三、代码模型构建准备工作一、简介 任务对象是Omniglot数据集上的few-shot classification任务&#xff0c;内容是利用元学习找到好的初始化参数。 Task: Few-shot Classification The…

在VSCode中使用Compaq Visual Fortran编译运行Frotran程序

本片文章主要是为了使用VSCode编译运行带QuickWin的老版本Fortran代码。 一、准备工作 安装VSCode和Compaq Visual Fortran6.6。 二、配置Fortran工程 用VSCode打开保存有Frotran代码的文件夹 建立.vscode文件夹&#xff0c;建立launch.json和task.json文件&#xff0c;分…

二、TCP/IP---Ethernet和IP协议

TCP/ip协议栈 OSI模型TCP/IP协议栈应用层&#xff0c;表示层&#xff0c;会话层应用层传输层主机到主机层&#xff08;传输层&#xff09;网络层网络层数据链路层&#xff0c;物理层网络接入层 Ethernet协议 以太网&#xff0c;实现链路层的数据传输和地址封装&#xff08;MA…

马蹄集 三角形坐标

三角形坐标 难度&#xff1a;青铜 ○时间限制&#xff1a;1秒 巴占用内存&#xff1a;64M 输入三角形三个顶点A,B,C的坐标(x,y),根据公式计算并输出三 角形面积。 S1/2*X1y2X2y33y1-X1y3-X2y1-x3y2 #include <bits/stdc.h> using namespace std; int main(){double x[4],…

Win10应用商店无法加载错误0x80072F7D怎么办?

Win10应用商店无法加载错误0x80072F7D怎么办&#xff1f;有用户开启电脑的Win10软件商店想要获取软件的时候&#xff0c;发现软件页面无法进行正常的加载&#xff0c;里面的内容显示为错误代码0x80072F7D。那么这个情况怎么去进行解决呢&#xff1f;一起来看看详细的解决方法分…

PMP证书到期了,有必要续吗?

我觉得续证是有需要的&#xff0c;毕竟证书有用的地方很多。 下面我们将从两方面分享&#xff1a; 1. PMP 证书在国内的含金量怎么样&#xff1f; 2. HR 如何看待 PMP 证书&#xff1f; 说到 PMP 证书的含金量&#xff0c;相信这个问题是所有人都关心的。对于如何来评判 PMP…

达芬奇密码题解

题目信息达芬奇隐藏在蒙娜丽莎中的数字列:1 233 3 2584 1346269 144 5 196418 21 1597 610 377 10946 89 514229 987 8 55 6765 2178309 121393 317811 46368 4181 1 832040 2 28657 75025 34 13 17711 记录在达芬奇窗台口的神秘数字串:36968853882116725547342176952286这道题…

Vue3——第十章(异步组件:defineAsyncComponent)

一、defineAsyncComponent基本使用 在大型项目中&#xff0c;我们可能需要拆分应用为更小的块&#xff0c;并仅在需要时再从服务器加载相关组件。Vue 提供了 defineAsyncComponent 方法来实现此功能&#xff1a; 如你所见&#xff0c;defineAsyncComponent 方法接收一个返回 P…