Android App 反应卡顿解决方案

Android App 反应卡顿,从技术上将就是UI 渲染慢。

UI渲染是从您的应用程序生成一个框架并将其显示在屏幕上的行为。 为了确保用户与您的应用程序的交互顺利,您的应用程序应该在16ms内渲染帧数达到每秒60帧(为什么60fps?)。 如果您的应用程序因UI渲染速度缓慢而受到影响,那么系统将被迫跳过帧,用户将感觉到您的应用程序中出现卡顿。 我们把这个叫做jank

本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:

1.UI 渲染简介
2.识别Jank
3.Fix Jank
4.引起Jank 通用问题举例

欢迎关注微信公众号:程序员Android
公众号ID:ProgramAndroid
获取更多信息

微信公众号:ProgramAndroid

我们不是牛逼的程序员,我们只是程序开发中的垫脚石。
我们不发送红包,我们只是红包的搬运工。

1.UI 渲染简介

为了帮助您提高应用程序质量,Android会自动监视您的应用程序是否有空,并在Android生命危险仪表板中显示信息。 有关如何收集数据的信息,请参阅Play Console文档。

如果您的应用程序出现问题,本页提供诊断和解决问题的指导。

Android生命危险仪表板和Android系统会跟踪使用UI Toolkit的应用程序的渲染时间统计信息(应用程序的用户可见部分是从CanvasView hierarchy绘制的)。

如果您的应用程序不使用UI Toolkit,就像使用VulkanUnityUnrealOpenGL构建的应用程序一样,则在Android Vitals仪表板中不提供时间统计信息。

您可以通过运行
adb shell dumpsys gfxinfo <package name>
来确定您的设备是否正在记录您的应用的渲染时间指标。

2.识别Jank

在您的应用程序中定位引起jank的代码可能很困难。 本部分介绍了三种识别jank的方法:

  • 1.Visual inspection

通过视觉检查,您可以在几分钟内快速浏览应用程序中的所有用例use-cases,但不能提供与Systrace相同的详细信息。

  • 2.Systrace

Systrace提供了更多的细节,但是如果你运行Systrace来处理应用程序中的所有用例,那么就会被大量的数据淹没,难以分析。

  • 3.Custom performance monitoring

Visual inspectionSystrace都会在你的本地设备上检测到。

如果不能在本地设备上重现,则可以构建自定义性能监视器Custom performance monitoring,以测量在现场运行的设备上应用的特定部分。

1. Visual inspection

目视检查可以帮助您识别正在生产结果的使用案例。 要执行视觉检查,请打开您的应用程序并手动检查应用程序的不同部分,然后查看非常粗糙的UI。 以下是进行目视检查时的一些提示:

  • 1.运行release 版本

运行您release应用程序的版本(或至少不可调试)的版本。ART运行时为了支持调试功能而禁用了一些重要的优化,所以确保你正在寻找类似于用户将看到的东西。

    1. 开启GPU渲染

开启步骤:
Settings -->Developer options -->Profile GPU rending

开启配置文件GPU渲染,会在屏幕上显示条形图,可以快速直观地显示相对于每帧16毫秒基准测试渲染UI窗口帧所花费的时间。
每个条都有着色的组件映射到渲染管道中的一个舞台,所以你可以看到哪个部分花费的时间最长。
例如,如果框架花费大量时间处理输入,则应该查看处理用户输入的应用程序代码。

开启 GPU 渲染效果图

    1. 留意特殊组件

有一些组件,如RecyclerView,是Jank普遍的来源。 如果您的应用程序使用这些组件,那么运行应用程序的这些部分是一个好idea

    1. App 冷启动导致

有时候,只有当应用程序从冷启动启动(Clod start)时,才能复制jank

  • 5.低内存情况下jank 比较容易出现

一旦你发现产生jank的用例,你可能会有一个很好的想法是什么导致你的应用程序的结果。 但是,如果您需要更多信息,则可以使用Systrace进一步深入研究。

2. Systrace

Systrace是一个显示整个设备在做什么的工具,并且它可以用于识别应用程序中的Jank。 Systrace的系统开销很小,所以在仪器使用过程中你会感受到app卡顿的存在。

Systrace记录跟踪,同时在设备上执行janky用例。 有关如何使用Systrace的说明,请参阅Systrace演练。 systrace被进程和线程分解。 在Systrace中查找应用程序的过程,应该如图所示。

Systrace分析应用程序

上面3个标注点解释

  1. 当卡顿时,会有掉帧发生,如上图1所示

Systrace显示何时绘制每个框架,并对每个框架进行颜色编码以突出显示较慢的渲染时间。 这可以帮助您查找比视觉检查更准确的单个janky框架。 有关更多信息,请参阅Inspecting Frames.

  1. 掉帧提示,如上图 2所示
    Systrace检测应用程序中的问题,并在各个框架和警报面板中显示警报。 警报中的以下指示是您的最佳选择。

  2. systrace timeline 如上图3 所示

Android框架和库的一部分(如RecyclerView)包含跟踪标记。 因此,systrace时间线会显示何时在UI线程上执行这些方法,以及执行多长时间。

如果systrace没有向您显示有关长时间使用UI线程工作的详细信息,则需要使用Android CPU Profiler来记录采样或检测的方法跟踪。 一般来说,method方法痕迹不适合用于识别排队,因为由于开销太大而产生假jank,并且无法看到线程何时被阻塞。 但是,method方法跟踪可以帮助您识别应用中花费最多时间的方法。 在识别这些方法后,add Trace markers a
标记并重新运行systrace,以查看这些方法是否引起混乱。
当记录systrace时,每个跟踪标记(执行的开始 Trace.beginSection();和结束Trace.endSection();对)会增加大约10μs的开销。 为了避免假Jank结局,不要将追踪标记添加到在一帧中被称为几十次的方法中,或者短于200us左右。

如需获取更多内容,请查看Systrace详解

3. Custom performance monitoring

如果您无法在本地设备上再现突发事件,则可以在您的应用中构建自定义性能监控,以帮助识别现场设备上的突发源。

为此,请使用FrameMetricsAggregator从应用程序的特定部分收集帧渲染时间,并使用Firebase性能监控记录和分析数据。

要了解更多信息,请参阅使用Use Firebase Performance Monitoring with Android Vitals.

3.Fix Jank

为了解决这个问题,请检查哪些帧在16.7ms内没有完成,并寻找出错的地方。Record View#draw在一些帧中抽取异常长度,或者可能是Layout? 查看下面4这些问题的常见来源,以及其他问题。

为了避免乱码,长时间运行的任务应该在UI线程之外异步运行。 一定要注意你的代码正在运行在哪个线程上,并且在向主线程发布不重要的任务时要小心。

如果您的应用程序有一个复杂而重要的主UI(可能是中央滚动列表),请考虑编写可自动检测缓慢渲染时间的测试测试,并经常运行测试以防止出现回归。 有关更多信息,请参阅自动化性能测试代码实验室。

4.引起Jank 通用问题举例

以下部分解释了应用程序中常见Jank问题 的来源,以及解决这些问题的最佳方案。

滑动 List

ListView和特别是RecyclerView通常用于复杂的滚动列表,这些列表最容易被忽略。 他们都包含Systrace标记,所以你可以使用Systrace来弄清楚他们是否有助于在你的应用程序jank。 一定要传递命令行参数-a <your-package-name>来获取RecyclerView中的跟踪部分(以及添加的任何跟踪标记)以显示出来。 如果可用,请遵循systrace输出中生成的警报的指导。 在Systrace里面,你可以点击RecyclerView-traced部分查看RecyclerView正在做的工作的解释。

RecyclerView: notifyDataSetChanged

如果您看到RecyclerView中的每个项目在一个框架中被反弹(并因此重新布局和重新绘制),请确保您没有调用notifyDataSetChanged()setAdapter(Adapter)swapAdapter(Adapter,boolean)为小更新。 这些方法表示整个列表内容已经改变,并且将在Systrace中显示为RV FullInvalidate。 而是在内容更改或添加时使用SortedListDiffUtil生成最小更新。

例如,考虑从服务器接收新闻内容列表的新版本的应用程序。 当您将该信息发布到适配器时,可以调用notifyDataSetChanged(),如下所示:

 

RecyclerView: notifyDataSetChanged


但是这带来了一个很大的缺点 - 如果它是一个微不足道的变化(也许单个项目添加到顶部),RecyclerView不知道 - 它被告知放弃所有的缓存项目状态,因此需要重新绑定一切。

 

最好使用DiffUtil,它将为您计算和分配最小的更新。

DiffUtil 使用

 

只需将您的MyCallback定义为DiffUtil.Callback实现,以通知DiffUtil如何检查您的列表。

RecyclerView: Nested RecyclerViews

嵌套RecyclerView是很常见的,特别是水平滚动列表的垂直列表(如Play Store主页上的应用程序的网格)。 这可以很好的工作,但也有很多意外四处移动。 如果在第一次向下滚动页面时看到很多内部项目膨胀,则可能需要检查是否在内部(水平)RecyclerViews之间共享RecyclerView.RecycledViewPools

默认情况下,每个RecyclerView将拥有自己的物品池。 如果在屏幕上同时显示一打itemViews,那么当itemViews不能被不同的水平列表共享的时候,如果所有的行都显示了相似类型的视图,那么这是有问题的。

RecyclerView: Nested RecyclerViews

如果要进一步优化,还可以在内部RecyclerViewLinearLayoutManager上调用setInitialPrefetchItemCount(int)
例如,如果您总是在一行中可见3.5项,请调用innerLLM.setInitialItemPrefetchCount(4);. 这将告诉RecyclerView,当一个水平行即将出现在屏幕上时,如果UI线程上有空闲时间,它应该尝试预取内部的项目

RecyclerView: Too much inflation / Create taking too long

UI线程则处于闲置状态下,RecyclerView中的预取功能应该有助于在大多数情况下通过提前完成工作来解决inflation Layout的成本问题。
如果您在一帧中看到inflation Layout(而不是标记为RV Prefetch的部分),请确保您正在测试最近的设备(Prefetch目前仅在Android 5.0 API Level 21及更高版本上支持),并使用最近版本的Support Library.

如果经常看到inflation Layout导致屏幕上出现新的Jank,验证出问题,请移除多余的View。 RecyclerView内容中的视图类型越少,当新的项目类型出现在屏幕上时,需要完成的inflation Layout就越少。

如果可能的话,将视图类型合并到合理的位置 - 如果只有图标,颜色或文本块在类型之间改变,则可以在绑定时间进行更改,并避免inflation Layout(同时减少应用程序的内存占用)。

如果您的视图类型看起来还不错,请考虑减少inflation Layout的成本。减少不必要的容器和结构视图可以帮助 - 考虑使用ConstraintLayout构建itemView,这可以很容易地减少结构视图。如果你想真正优化性能,你的项目层次结构是简单的,并且你不需要复杂的themingstyle的功能,请考虑自己调用构造函数 - 但请注意,它往往是不值得的损失的简单性和功能的权衡XML。

RecyclerView: Bind taking too long

绑定(即onBindViewHolder(VH,int))应该是非常简单的,除了最复杂的项目之外的所有项目都要花费少于一毫秒的时间。 它只需从adapter's的内部项目数据中获取POJO项目,然后在ViewHolder中的视图上调用setter。 如果RV OnBindView需要很长时间,请确认您在绑定代码中做了最少的工作。

如果您使用简单的POJO对象来保存适配器中的数据,则可以完全避免使用Data Binding l
库来将绑定代码写入onBindViewHolder

RecyclerView or ListView: layout / draw taking too long

有关绘制和布局的问题,请参阅 Layout and Rendering Performance.

ListView: Inflation

如果你不小心,ListView很容易会被意外回收。 如果每次屏幕显示项目时都看到inflation Layout,请检查Adapter.getView()的实现是否正在使用,重新绑定并返回convertView参数。 如果你的getView()实现总是inflation Layout,你的应用程序将无法从ListView中获得回收的好处。 你的getView()的结构几乎总是类似于下面的实现:

复用 convertView

Layout performance

如果Systrace显示Choreographer#doFrame的布局部分工作太多,或者工作频繁,这意味着您遇到了布局性能问题。 您的应用的布局性能取决于View层次结构的哪个部分具有更改布局参数或输入。

Layout performance: Cost

如果段长度超过几毫秒,则可能是针对RelativeLayouts或weighted-LinearLayouts.
的最差嵌套性能。

这些布局中的每一个都可以触发其子项的多个measure/layout传递,因此嵌套它们会导致嵌套深度上的O(n ^ 2)行为。 请尝试避免使用RelativeLayoutLinearLayoutweight特征,除了层次结构的最低叶节点之外的所有特征。 有几种方法可以做到这一点:

  • 优化View结构
  • 使用自定义View
  • 尝试转换到ConstraintLayout,它提供了类似的功能,并且没有性能上的缺陷。

Layout performance: Frequency

当新内容出现在屏幕上时,将会发生新的Layout,例如,当一个新项目在RecyclerView中滚动查看时。 如果在每个框架上都发生重要的布局,则可能是在布局上进行动画处理,这很可能导致丢帧。 通常,动画应该在View的绘图属性(例如setTranslationX / Y / Z()setRotation(),setAlpha()等)上运行。 这些都可以比Layout属性(如填充或边距)更好地更改。 通常通过调用触发invalidate()setter,然后在下一帧中绘制(Canvas),来更改视图的绘制属性。 这将重新记录无效的视图的绘图操作,并且通常也比布局好得多。

Rendering performance渲染性能

Android UI在两个阶段工作 - 在UI线程Record View#draw,在RenderThread上绘制DrawFrame。 第一次运行在每个无效的View上绘制(Canvas),并可能调用自定义视图或代码。 第二个在本地RenderThread上运行,但是将根据Record View#draw阶段生成的工作进行操作。

Rendering performance: UI Thread

如果Record View#draw需要很长时间,则通常是在UI线程上绘制位图的情况。 绘制位图需要使用CPU渲染,一般应该避免在主线程中绘制。 您可以使用Android CPU分析器的方法跟踪来查看这是否是问题。

绘制位图通常是在应用程序想要在显示位图之前修饰位图的时候完成的。 有时候像装饰圆角的装饰:

绘制圆角图片


如果这是您在UI线程上所做的工作,则可以在后台的解码线程上执行此操作。 在这样的一些情况下,你甚至可以在绘制时做这个工作,所以如果你的Drawable或View代码看起来像这样:

性能差代码

 

可以将上面代码优化为如下:

优化性能的代码

请注意,这通常也可以用于后台保护(在位图顶部绘制渐变)和图像过滤(使用ColorMatrixColorFilter),以及修改位图的其他两种常见操作。

如果由于其他原因(可能将其用作缓存)绘制到位图,则尝试绘制直接传递到ViewDrawable的硬件加速硬件,如有必要,可考虑使用LAYER_TYPE_HARDWARE调用setLayerType()来缓存复杂的渲染 输出,并仍然利用GPU渲染。

Rendering performance: RenderThread

一些canvas操作是便小的消耗,但触发RenderThread昂贵的计算。 Systrace通常会通知这些。

Canvas.saveLayer()

避免Canvas.saveLayer() - 它可以触发昂贵的,未缓存的,离屏渲染每一帧。 尽管Android 6.0的性能得到了提高(当进行优化以避免GPU上的渲染目标切换时),但是如果可能的话,避免使用这个昂贵的API仍然是好事,或者至少确保您通过CLIP_TO_LAYER_SAVE_FLAG(或者调用一个变体 不带标志)。

Animating large Paths

当硬件加速Canvas传递给Views时,Canvas.drawPath()被调用,Android首先在CPU上绘制这些路径,然后将它们上传到GPU。 如果路径较大,请避免逐帧编辑,以便高速缓存和绘制。 drawPoints(),drawLines()和drawRect / Circle / Oval / RoundRect()更有效率 - 即使最终使用更多的绘制调用,最好使用它们。

Canvas.clipPath

clipPath(Path)触发了昂贵的裁剪行为,通常应该避免。 如果可能,选择绘制形状,而不是剪裁到非矩形。 它性能更好,支持抗锯齿。 例如,下面的clipPath调用:

Canvas.clipPath

Bitmap uploads

Android将位图显示为OpenGL纹理,并且首次在一帧中显示位图时,将其上传到GPU。您可以在Systrace中将此视为上传宽度x高度纹理。这可能需要几个毫秒(见下图),但是有必要用GPU显示图像。

位图绘制

 

如果这些花费很长时间,请首先检查轨迹中的宽度和高度数字。确保正在显示的位图不比显示的屏幕区域大得多。如果是,则浪费上传时间和内存。通常位图加载库提供了简单的方法来请求适当大小的位图。

Android 7.0中,位图加载代码(通常由库完成)可以在需要之前调用prepareToDraw()来及早触发上传。这样上传发生的早,而RenderThread空闲。这可以在解码之后完成,也可以在将位图绑定到View时进行,只要知道位图即可。理想情况下,你的位图加载库会为你做这个,但是如果你正在管理你自己的,或者想确保你没有在新设备上点击上传,你可以在你自己的代码中调用prepareToDraw()

Thread scheduling delays

线程调度程序是Android操作系统的一部分,负责决定系统中哪些线程应该运行,何时运行以及运行多长时间。 有时候,因为你的应用程序的UI线程被阻塞或者没有运行,就会发生Jank。 Systrace使用不同的颜色来指示线程正在Sleep(灰色)Runnable(蓝色:可以运行,但调度程序还没有选择它运行)正在运行(绿色)中断(红色或橙色)。 这对于调试线程调度延迟导致的Jank`问题非常有用。

注意:
旧版本的Android更频繁地遇到不是应用程序故障的调度问题。 在这方面进行了不断的改进,所以考虑在最近的操作系统版本上更多的调试线程调度问题,在这些版本中,被调度的线程更可能是应用程序的错误。

线程渲染过程

UI线程RenderThread预计不会运行时,有框架的一部分。 例如,UI线程RenderThreadsyncFrameState正在运行并且上传位图时被阻塞 - 这是因为RenderThread可以安全地复制UI线程所使用的数据。 另一个例子是,RenderThread在使用IPC时可以被阻塞:在帧的开始处获取缓冲区,从中查询信息,或者通过eglSwapBuffers将缓冲区传回给合成器。

在您的应用程序的执行中经常会有很长时间的暂停,这些都是由Android上的进程间通信(IPC)机制进行的。 在最近的Android版本中,这是UI线程停止运行的最常见原因之一。 一般来说,修正是为了避免调用函数来调用binder; 如果这是不可避免的,那么应该缓存该值,或将工作移动到后台线程。 随着代码库变得越来越大,如果不小心的话,通过调用一些低级别的方法,很容易意外地添加了一个binder调用,但是使用跟踪来发现和修复它们也是很容易的。

如果您有绑定事务,则可以使用以下adb命令来捕获其调用堆栈:

adb 命令捕获堆栈信息

 

有时像getRefreshRate()这样的无害的表面调用可能会触发绑定事务,并在频繁调用时导致严重的问题。 定期跟踪可以帮助您快速找到并解决这些问题。

UI Thread sleeping due to binder transactions in a RV fling

如果你没有看到绑定Activity,但仍然没有看到你的UI线程运行,请确保你没有等待来自另一个线程的锁定或其他操作。 通常,UI线程不应该等待来自其他线程的结果 - 其他线程应该向其发布信息post message.

Object allocation and garbage collection

对象分配和垃圾回收(GC)已经成为一个问题,因为ARTAndroid 5.0中默认运行时引入的,但是仍然有可能通过这些额外的工作来减轻你的线程负担。 对于每秒钟不会发生多次的罕见事件(如用户单击按钮)进行分配是很好的做法,但要记住,每次分配都需要付出一定的代价。 如果它处于一个频繁调用的紧密循环中,请考虑避免分配来减轻GC上的负载。

Systrace会告诉你GC是否频繁运行,Android Memory Profiler可以显示你的分配来自哪里。 如果你可以避免分配,特别是在紧密的循环中,你应该没有问题。

shows a 94ms GC on the HeapTaskDaemon thread

 

在最新版本的Android上,GC通常在名为HeapTaskDaemon的后台线程上运行。 请注意,大量的分配可能意味着更多的CPU资源花费在GC上.

至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

如有侵权,请联系小编,小编对此深感抱歉,届时小编会删除文章,立即停止侵权行为,请您多多包涵。

既然都看到这里,领两个红包在走吧!
以下两个红包每天都可以领取

1.支付宝搜索 522398497,或扫码支付宝红包海报。

支付宝扫一扫,每天领取大红包

2.微信红包,微信扫一扫即可领取红包

 

微信扫一扫,每天领取微信红包

小礼物走一走,来简书关注我

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中文大模型评估基准:C-EVAL: A Multi-Level Multi-Discipline Chinese Evaluation Suite for Foundation Models

论文&#xff1a;https://arxiv.org/abs/2305.08322 网站&#xff1a;C-Eval: A Multi-Level Multi-Discipline Chinese Evaluation Suite for Foundation Models 一、导言 随着大语言模型的迅速发展&#xff0c;如何评估一个大模型的能力也成为了一个重要的话题&#xff0c…

「国际科技信息中心SCITIC论坛」从细胞、基因和人工智能,探讨智慧医疗的机遇和挑战...

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 2023年3月22日&#xff0c;由国际科技信息中心主办&#xff0c;AI TIME承办的SCITIC论坛“细胞&#xff0c;基因和人工智能&#xff1a;探索医学研究的未来”完美收官。SCITIC论坛由国际科技信息中心倾力打造&a…

C-Eval:构造中文大模型的知识评估基准

作者&#xff1a;符尧&#xff0c;何俊贤 排版&#xff1a;宋梓瑜 来源&#xff1a;海外独角兽 本项目立项于 2023 年 2 月 28 日&#xff0c;由上海交通大学、清华大学和爱丁堡大学共同完成&#xff0c;发布于 2023 年 5 月 22 日&#xff0c;原文链接&#xff1a;https://yao…

GPT(Chat)原理及其应用

摘要 遥想以往&#xff0c;人类沟通的方式只有口头或书面文字&#xff0c;但现在随着科技的发展&#xff0c;人类的沟通方式又得到了革命性的变化&#xff0c;即通过聊天机器人实现人机沟通。而GPT(Chat)中文聊天机器人又是其中的一种&#xff0c;它可以通过技术手段来自然地与…

AI:什么是智能?

本篇文章是博主在人工智能等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在学习摘录和笔记专…

ChatGPT推荐的开源项目,到底靠不靠谱?

今天我们让ChatGPT推荐一些开源项目&#xff0c;看看这些项目到底靠不靠谱&#xff1f; 首先&#xff0c;我们需要明确一个概念&#xff0c;那就是什么是开源项目。开源项目是指代码开放、可自由使用、修改和分发的软件项目。开源项目的优点显而易见&#xff0c;它们免费、透明…

餐饮行业最新的经营模式——私域运营案例

疫情让许多企业发展面临巨大压力&#xff0c;而私域流量在这个时刻成为很多餐饮企业爱如珍宝的“救命稻草”。甚至有人预言&#xff0c;今年将可能是餐饮私域流量醒觉得第一年。目睹着越来越多的餐饮企业其中甚至还有餐饮大牌企业都加入私域流量中来。但好多餐饮人都不太了解私…

基于PHP的餐饮行业管理系统

第一章 绪论 1.1 系统开发背景 近年来&#xff0c;基于用户对网络信息传递的实时性以及高效性等方面的需求&#xff0c;使得信息化技术手段以及相关的产业结构得到的飞速的发展&#xff0c;其中最为出众的当属电商化的运营管理模式&#xff0c;其一经推广便受到了广泛的关注。…

【完善】微信餐厅点单小程序+后台管理系统的设计与实现(python实现)

前言 本文为完善上一篇文章餐厅点单小程序后台管理管理系统的设计与实现&#xff0c;旨在帮助有需要的小伙伴&#xff0c;更好的入门学习python3 djangovue开发的前后端分离框架。话不多说&#xff0c;开始我们的学习吧&#xff5e; 项目介绍 本次系统设计分两大模块&#x…

餐饮门店数字化转型|餐厅管理系统小程序

餐饮行业规模非常庞大&#xff0c;每年都有大量公司或个体户入局&#xff0c;国内各类美食非常多&#xff0c;不同品类菜品都有大量需求&#xff0c;以前几乎在业的餐饮门店&#xff0c;只要运营得当&#xff0c;挣多挣少总归是有利的&#xff0c;也能很好的生存下去&#xff0…

【餐厅点餐平台|一】项目描述+需求分析

餐厅点餐平台导航 【餐厅点餐平台&#xff5c;一】项目描述需求分析 https://blog.csdn.net/weixin_46291251/article/details/126414430 【餐厅点餐平台&#xff5c;二】总体设计 https://blog.csdn.net/weixin_46291251/article/details/126422811 【餐厅点餐平台&#xff5…

校园外卖点餐系统——Day02【员工管理业务开发】

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

餐道中台如何赋能餐饮零售企业?

前不久&#xff0c;餐道A轮融资1亿元&#xff0c;是近期餐饮行业信息化领域最大的一笔。这家公司融资的目的是为了加强“SaaS 业务数据双中台”系统研发。那么&#xff0c;这家公司是谁&#xff0c;为什能拿到融资&#xff0c;此次融资之后会朝着何处发展&#xff0c;为业内带来…

餐饮行业管理系统技术开发详细步骤详解

一. 项目介绍 本系统主要应用在餐饮行业&#xff0c;可以适用于中餐、西餐、快餐、火锅、烤肉等&#xff0c;主要功能分前端和后端两部分。前端主要完成就餐客户的餐厅预定及点菜环节&#xff0c;后端主要完成餐厅、餐桌的设置&#xff0c;菜品的设置等 系统分为前端和后台两…

教你如何实现门店餐饮快速裂变的解决方案

随着互联网市场的迅速发展&#xff0c;很多实体店受到电商行业的影响&#xff0c;客流量是越来越少&#xff0c;再加上这几年的疫情影响&#xff0c;实体店真的是越来越难做了特别是餐饮行业&#xff0c;以至于身边随处可见的门店关门、转让。难道就实体店就走向谷底了吗&#…

外卖项目01---软件开发整体介绍

目录 一、软件开发整体介绍 03 1.1软件开发流程 03 1.2角色分工 1.3软件环境 二、外卖项目介绍 04 2.1项目介绍 2.2产品原型展示 2.3技术选型 2.4功能架构 2.5项目上线后的角色分类 三、开发环境搭建 05 3.1数据库环境搭建 3.2maven项目搭建 06 四、后台登陆功…

如何为餐饮商家打造代运营解决方案?

外卖行业成餐饮主战场之一&#xff0c;食咖助力商户抢占流量入口 外卖行业是目前餐饮的另外一个非常重要的主战场&#xff0c;作为其细分领域&#xff0c;外卖代运营主要集中在产业图谱中的平台端口&#xff0c;食咖代运营的核心&#xff0c;是运营团队落地助力商户抢占线上的…

案例:基于大数据的餐饮公司会员营销及O2O应用策略

来源&#xff1a;软件定义世界 主讲嘉宾&#xff1a;龚光宇&#xff0c;上海一茶一坐餐饮有限公司CIO&CMO&#xff0c;来自台湾&#xff0c;24年IT工作经验&#xff0c;2004年加入上海一茶一坐餐饮有限公司任CIO&#xff0c;2012年兼任CMO&#xff0c;2011年IT经理世界中国…

餐饮企业提升用户价值,从基于点单链路的精细化运营开始

近几年&#xff0c;餐饮业的经营增长面临着巨大挑战&#xff0c;在这种情况下&#xff0c;餐饮企业如何提升用户价值&#xff0c;提高多风险下持续增长的动力呢&#xff1f;神策数据杨丽月聚焦用户运营&#xff0c;围绕“一条链路&#xff0c;四个指标”&#xff0c;跟大家分享…

Whale帷幄 - 餐饮店怎么运营管理 餐饮门店运营管理方案

您在管理门店时&#xff0c;是否有这些烦恼&#xff1f; 数据四处分散&#xff0c;难以统一采集治理门店规范不一致&#xff0c;难以远程实时监督线下门店体验差&#xff0c;难以洞察顾客轨迹门店运营成本高&#xff0c;难以评估业绩ROI 帷幄空间数据平台&#xff08;SDP&…