您好!欢迎来到爱源码

爱源码

热门搜索: 抖音快手短视频下载   

安卓性能优化——启动优化提升60% 《电影网站源码》

  • 时间:2022-08-31 02:18 编辑: 来源: 阅读:290
  • 扫一扫,手机访问
摘要:安卓性能优化——启动优化提升60% 《电影网站源码》
1.应用程序启动速度。一个应用app的启动速度可以影响客户的第一次体验。启动速度慢(感官)的应用可能会导致客户再次打开该应用的意愿降低,或者客户可能会卸载并放弃该应用。 本文将从两个方向优化应用的启动速度:视觉体验优化代码逻辑优化2。视觉优化Google开发文档https://developer . Android . com/topic/performance/vitals/launch-time。应用程序启动有三种状态,每种状态都会影响应用程序对客户可见所需的时间:冷启动、热启动和热启动。 冷启动时,应用程序从头开始。 在其他状态下,系统需要将正在运行的应用从后端运行到前端。 我们建议您始终根据冷启动的假设进行优化。 这也可以提高热启动和热启动的性能。 冷启动开始时,系统有三项任务 这些任务是:加载和启动应用程序 启动后会立即显示应用程序的空白启动窗口。 创建应用程序流程 一旦系统创建了申请流程,申请流程将负责下一阶段。 这几个阶段分别是:创建app对象,启动主线程,创建应用入口的Activity对象,填充加载布局视图,执行视图在屏幕上的绘制过程。度量->:布局->;draw应用程序进程完成第一次绘制后,系统进程会交换当前显示的背景窗口,用主活动替换。 此时,客户可以开始使用该应用程序。 因为App应用程序流程的创建过程是由手机的硬件和软件决定的,我们只能在这个创建过程中优化视觉。 启动主题优化冷启动阶段:1。加载并启动应用程序。 2.启动后立即显示应用程序的空白启动窗口。 3.创建应用程序流程 所谓主题优化,就是设置应用冷启动时(1~2阶段)启动窗口的主题。 现在,当App应用程序启动时,它将首先进入一个LaunchActivity来显示应用程序信息。 1.默认情况下,如果我们不解决app(设置默认主题),在应用中初始化其他第三方服务(假设加载需要2000ms),那么冷启动过程会如下图所示:系统默认启动应用时会启动空白窗口,直到成功创建App的入口活动并绘制视图。 (大概是onWindowFocusChanged方法回调的时候)2。透明主题优化解决了启动窗口白屏的问题。很多开发者用透明主题来处理这个问题,但是治标不治本。 虽然解决了上述问题,但仍有不足之处。 & lt!-基本应用程序主题。-& gt;& ltstyle name = " app Theme " parent = " Theme。AppCompat.Light.DarkActionBar " >& ltitem name = " Android:window full screen " & gt;true & lt/item & gt;& ltitem name = " Android:windowIsTranslucent " & gt;true & lt/item & gt;& lt/style & gt;3.设置启动画面的主题。为了更流畅无缝的连接我们的闪屏页面,你可以在启动活动的主题中设置闪屏图片,这样启动窗口的图片就会是闪屏图片而不是白屏。 & lt!-基本应用程序主题。-& gt;& ltstyle name = " app Theme " parent = " Theme。AppCompat.Light.DarkActionBar " >& ltitem name = " Android:window background " & gt;@ MIP map/launch & lt;/item & gt;//闪屏页面图片< item name = " Android:window full screen " & gt;true & lt/item & gt;& ltitem name = " Android:windowContentOverlay " & gt;@ null & lt/item & gt;& lt/style & gt;如果这样设置,冷启动时会显示闪屏页面的图片,然后App进程会初始化加载门户活动(也是闪屏页面),可以无缝连接。 其实这种方式并没有真正加快应用进程的启动速度,只是优化了客户的视觉效果带来的体验。 3代码优化当然,上面设置主题的方法是用来优化客户体验的效果。关键在于代码的优化。 首先可以统计一下应用的冷启动时间。 冷启动时间统计adb命令统计参考如何计算App http://www.androidperformance.com/December 2015年31期启动时间/how-to-calculation-Android-App-lunch-time/Adb命令:adb shell am start -S -W包名/启动类的全限定名,-S表示重启当前应用的更多Adb命令mzlogin/awesome-adbc:\ Android \ demo >;亚行壳牌am start-S-W com.example.moneyqian.demo/ com . example . money Qian . demo . mainactivitystopping:com . example . money Qian . demo starting:Intent { act = Android . Intent . action . main cat =[Android . Intent . catego ry .LAUNCHER]CMP = com . example . money Qian . demo/。主要活动}状态:正常活动:com.example.moneyqian.demo/。mainactivityshitime:2247总时间:2247等待时间:2278完成本次:上一个活动的启动时间(例如从launch Activity->:Main Activity“ADB命令进入的活动”,只统计主活动的启动时间)total time:启动一系列活动的总时间。(数几个活动)WaitTime:申请流程的创建过程+TotalTime。在第一个时间段,创建AMS ActivityRecord记录块并选择合适的任务,暂停当前简历的活动。第二个时间段,启动流程,无接口调用活动的onCreate(),无接口暂停/完成活动。在第三个时间段,调用onCreate,onresume。//Activityrecordprivate void report launch time用接口activity { ` ` ` ` ` ` `` final long this time = curtime-display start time;final long total time = stack . mlaunchstarttime!= 0 ?(curTime-stack . mlaunchstarttime):this time;}最后总结一下:如果你需要统计从点击桌面图标到活动启动完成的时间,可以用WaitTime作为标准,但是系统的启动时间是无法优化的,所以我们只需要关心这个时间就可以优化冷启动了。 此外,系统日志统计可用于根据系统日志统计启动时间。要在Android Studio中查找经过的时间,您必须在logcat视图中禁用过滤器(无过滤器)。 因为这是系统的日志输出,而不是应用程序的 您还可以检查其他应用程序的启动时间。 过滤显示输出的启动日志。3.代码优化根据上面启动时间的输出统计,我们可以记录优化前的冷启动时间,然后和优化后的启动时间进行对比。 优化应用作为应用的整个初始化配置入口,往往承担着不该有的负担~很多第三方组件(包括App应用本身)率先进入应用,完成初始化操作。 但是,应用程序中繁重的初始化和复杂的逻辑会影响应用程序的启动性能。通常,有机会优化这些任务以实现性能改进。这些常见问题包括:复杂的布局初始化阻塞了主线程的UI绘制操作,例如,I/O读写,或者网络访问。位图大图或VectorDrawable加载其他占用主线程的操作,我们可以根据这些组件的优先级来对初始化进行分类:必须在主线程中立即初始化必要的组件(可能会立即使用entry活动)。组件必须在主线程中初始化,但是初始化可以延迟。 组件可以在子线程中初始化。 建议延迟放置在子线程中的组件的初始化,这样可以了解是否会影响项目!因此,针对以上分析,我们可以对项目中Application的加载组件进行如下优化:将Bugly、x5内核初始化、SP读写、友盟等组件放到子线程中进行初始化。 (子线程的初始化不能影响组件的使用)new thread(newrunnable(){ @ override public void run(){//设置线程的优先级,不要和主线程抢资源。SethreadPriority(process . thread _ priority _ background);//子线程初始化第三方组件thread . sleep(5000);//建议延迟初始化,以便发现是否能影响其他功能或者死机!}}).start();延迟加载需要在主线程中初始化但不需要立即完成的动作(我本来想在portal Activity中做这个,但是把组件的初始化放在应用中统一管理会更好。)处理程序。post delayed(new runnable(){ @ override public void run(){//延迟组件的初始化}},3000);最终,闪屏页面业务优化只剩下几个组件需要在主线程中初始化,比如嵌入、点击流、数据库初始化等。,但这些消耗的时间可以在其他地方抵消。 背景:应用app通常会设置一个固定的闪屏页面显示时间,比如2000ms,所以我们可以根据客户手机的运行速度来调整显示时间,但是总时间还是2000ms。 启动页面的总显示时间=组件初始化时间+剩余显示时间。 也就是总时间2000ms,组件初始化800ms,然后可以显示1200 ms。 我们先来了解一下Application的启动过程。图片摘自:如何统计安卓App https://www.jianshu.com/p/59a2ca7df681.的启动时间虽然下图的源代码不是最新的源代码(5.0源代码),但不影响整个过程。 (7.0、8.0方法名称将会改变) 在冷启动过程中,系统会初始化应用程序进程,创建应用程序等任务。此时,将显示一个启动窗口,启动窗口。如上分析,如果没有优化主题,就是白屏。 如果你想了解更多的启动过程源代码,可以看我的博客:Launcher启动Activity的工作过程。通过分析https://blog.csdn.net/qian520ao/article/details/78156214,的源代码我们可以知道,应用程序初始化后,会调用attachBaseContext()方法,然后调用应用程序的onCreate()方法,再创建并执行entry活动的onCreate()方法。 所以我们可以在应用程序中记录启动时间。 //Application @ override protected void attachBaseContext(Context base){ super . attachBaseContext(base);sputil . putlong(" application _ attach _ time ",system . current time millis());//记录应用初始化时间}有了启动时间,我们就要知道门户的攻击性展现给客户的时间(视图绘制完成)。从博客(视图的工作流程)中了解到,onWindowFocusChanged()的回调时间表示可以获得客户的触摸时间,视图绘制的过程结束,所以我们可以用这个方法记录显示时间。 Https://blog.csdn.net/qian520ao/article/details/78657084//入口活动@ override public void onwindowfocuschange(boolean hasfocus){ super . onwindowfocuschange(hasfocus);long app attach time = sputil . get long(" application _ attach _ time ");long diffTime = system . current time millis()-app attach time;//从申请到进入活动的时间//所以splash页面的显示时间是2000ms-diffTime。}所以我们可以动态设置应用闪屏的显示时间,尽量让每部手机的显示时间一致,让手机配置不高的客户不会感受到闪屏时间的漫长和难熬(比如初始化2000ms,需要2000ms闪屏时间),优化客户体验。 页面优化闪屏后,会显示金主爸爸们的广告页面。 由于项目中广告页面的图片可能是大图和APng动态图,所以需要将这些图片下载到本地文件,下载完成后再显示。这个过程经常会遇到以下两个问题:1 .广告页面的下载是一个异步的过程,所以我们经常不知道将它们加载到页面的正确时间。 2.保存广告页面。因为保存是I/O流操作,很可能会被客户中断,下次会得到损坏的图片。 因为我们不了解客户的网络环境,所以有些客户下载广告页面可能需要一段时间,这个时候不可能无限期等待。 所以要解决这个问题,可以打开IntentService下载广告页面图片。 1.打开门户倡议中的IntentService,下载广告页面。 或其他异步下载操作。 2.记录广告页图片文件流写完之后的图片大小,或者记录一个标识符。 在下一次广告页面加载时,可以判断广告页面图片是否已经下载,图片是否完整,否则删除并重新下载图片。 此外,闪屏页面中还有剩余的显示时间,因此如果客户已经下载了图片,并且图片完整,则可以显示广告页面。 否则进入主活动,因为IntentService继续在后端默默下载保存图片~4。优化前优化效果:Displayed Launch Activity+2s 526 ms+1s 583 ms+2s 603 ms+1s 533 ms+2s 372 ms+1s 556 ms优化后:Displayed Launch Activity inactivity+1s 191 ms+911 ms+1s 101 ms+903 ms+1s 187 ms已通过上述手机的启动测试,发现优化后的App冷启动启动速度提升了60%!!!而我们可以看看手机再次冷启动时的内存情况:优化前:随着大量对象的创建和回收,系统在15s内GC 5次。 内存使用波动。 优化后,对象将创建在一个稳定的上升状态,系统将在15s内GC两次。 (后期业务发展增加了新的功能,所以增加了代码量。 )之后,总内存使用量缓慢下降。 其他:应用使用的内存不确定如何分类。 代码:用于求解代码和资源的内存(如dex字节码,优化或编译的dex代码,。所以库和字体)。 堆栈:应用程序中本地堆栈和Java堆栈使用的内存 这通常与应用程序运行的线程数量有关。 图形:图形缓冲队列用来显示像素(包括GL表面,GL纹理等)的内存。)到屏幕上。 (请注意,这是和CPU共享的内存,不是GPU专用的内存。 )Native:从C或C++代码中分配的对象内存 即使应用程序中没有使用C++,您也可能会看到这里使用了少量的本机内存。因为Android框架使用原生内存来解决各种任务,比如解决图像资源和其他图形,即使代码是用Java或者Kotlin语言写的。 Java:从Java或Kotlin代码中分配的对象内存 Allocated:应用分配的Java/Kotlin对象的数量。 它不计算在C或C++中分配的对象 查看更多:https://developer . Android . Google . cn/studio/profile/memory-profiler?Hl=zh-cn5。开始窗口优化我们的代码后,分析开始窗口的源代码。 基于android-25 (7.1.1)的启动窗口是由WindowManagerService统一管理的窗口。一般用作冷启动页面进入活动的预览窗口。ActivityManagerService决定启动窗口能否显示,并不是每个活动都启动和跳转。 WindowManagerService通过窗口管理策略类PhoneWindowManager创建启动窗口。 拿我之前的源代码分析文章中的启动流程图来大致看一下:Launcher启动活动的工作流程。https://blog.csdn.net/qian520ao/article/details/78156214开门见山,在ActivityStarter的startActivityUnchecked()方法中,调用了ActivityStack(活动状态管理)的startActivityLocked()方法。 此时,活动仍在启动,窗口不显示。 前面的流程图显示了启动窗口的显示过程。 首先,活动状态管理器ActivityStack启动显示启动窗口的过程。 //ActivityStackfinal void startActivityLocked(activity record r,boolean newTask,boolean keepCurTransition,activity options options){ ` ` ` ` ` ` if(!isHomeStack()| | numActivities()& gt;0) {//HOME_STACK表示Launcher的桌面所在的堆栈//1。第一,当前启动栈不在Launcher的桌面栈中,当前系统已经激活了Activity boolean doShow = trueIf (newTask) {// 2。要将此活动组件放入新的任务堆栈中,请启动if((r . Intent . get flags())& Intent。FLAG _ ACTIVITY _ RESET _ TASK _ IF _ NEEDED)!= 0){ resettaskifneedlocked(r,r);do show = toprunningnodelaydactivitylocked(null)= = r;} } else if(选项!= null & amp& ampoptions . getanimationtype()= = activity options。ANIM _场景_过渡){ doShow = false} if(r . mlaunchtaskbahead){//3。热启动,无需启动窗口mwindowmanager . setapp visibility(r . app token,true);ensureActivitiesVisibleLocked(null,0,PRESERVE _ WINDOWS);} else if(SHOW _ APP _ STARTING _ PREVIEW & amp;& ampdo show){ ` ` ` ` ` `//4。显示启动窗口R. ShowStartingWindow (Prev,ShowStartingIcon);}} else {//桌面启动器当前已启动//如果这是第一个活动,不要做任何动画,//因为它上面没有任何动画。` ` ` ` ` `}}首先确定当前要启动的活动是否不在Launcher栈中,要启动的活动是否可以在新任务中。而且没有转场动画。如果是热/温启动,则不需要启动窗口。直接设置App的可见性。然后调用ActivityRecord的showStartingWindow()方法设置启动窗口,改变当前窗口的状态。 如果app的应用进程已经创建,门户活动已经准备好,可以根据mStartingWindowState判断启动窗口是否需要关闭。 //ActivityRecordvoid showStartingWindow(activityrecordprev,boolean createifneed){ final compatibility info compatiinfo = service . compatibility info for packagelocked(info . application info);final boolean showed = service . mwindowmanager . setappstartingwindow(app token,packageName,theme,compatInfo,nonLocalizedLabel,labelRes,icon,logo,windowFlags,prev!= null?prev.appToken : null,createIfNeeded);if(showed){ mStartingWindowState = STARTING _ WINDOW _ showed;}}WindowManagerService会判断当前活动的令牌和主题。 //WindowManagerService @ override public Boolean setAppStartingWindow(I binder token,String pkg,int theme,CompatibilityInfo compatInfo,CharSequence nonLocalizedLabel,int labelRes,int icon,int logo,int windowFlags,IBinder transferFrom,Boolean if need){ synchronized(mwindowmap){//1 .启动窗口也是需要令牌的appwindowtoken w token = findappwindowtoken(token);//2.如果已经设置了启动窗口,就不要继续求解if (wtoken.startingData!= null) {返回false}如果(主题!= 0) { AttributeCache。entry ent = attribute cache . instance()。get(pkg,theme,com . Android . internal . r . style able . window,mCurrentUserId);//3.一堆代码判断主题。如果不符合要求,则不会显示启动窗口(如透明主题)if(windowistranslucent){ return false;} if(windowIsFloating | | windowDisableStarting){ return false;} ``````````}//4.创建StartingData并发送消息wtoken . starting data = new starting data(pkg,theme,compatInfo,nonLocalizedLabel,labelRes,icon,logo,window flags);message m = MH . obtain message(H . ADD _ STARTING,w token);MH . sendmessageatfrontofqueue(m);}返回true}启动窗口也需要和Activity有相同的token token。虽然启动窗口可能是白屏,也可能是图片,但还是需要经历绘制过程。该窗口已通过WMS展示。 StartingData对象用于表示启动窗口的相关数据,描述启动窗口的视图信息。 如果当前活动是透明主题或浮动窗口等。,那么就不需要启动窗口来过渡启动过程,所以在上面的视觉优化中设置了透明主题的时候就不显示白色的启动窗口了。 启动窗口也很紧急。WMS的内部类H (handler)在主线程中解析消息,所以当前消息需要放在队列的最前面。 PS:为什么需要通过Handler发送消息?你可以在所有的主要服务中看到Handler,它们可能都有一个挂名h,因为一些可能调用这个服务的执行方法在子线程中,Handler的职责就是把它们切换到主线程中,它也可以统一管理调度。 更多了解Handler,请参考文章:你真的了解Handler吗?https://blog . csdn . net/Qian 520 ao/article/details/78262289//WindowManagerService-& gt;h public void handle Message(Message msg){ switch(msg . what){ case ADD _ STARTING:{ final AppWindowToken w token =(AppWindowToken)msg . obj;最终starting data SD = w token . starting data;View view = null请尝试{最终配置overrideConfig = wtoken!= null & amp& ampwtoken.mTask!= null?WTO ken . mtask . moverrideconfig:null;view = m policy . addstartingwindow(w token . token,sd.pkg,sd.theme,sd.compatInfo,sd.nonLocalizedLabel,sd.labelRes,sd.icon,sd.logo,sd.windowFlags,override config);} catch(Exception e){ slog . w(TAG _ WM,“添加起始窗口时出现异常”,e);} ` ` ` ` `} break;}在当前的handleMessage方法中,它将在主线程中求解消息。得到token和StartingData的启动数据后,通过mPolicy.addStartingWindow()方法将启动窗口添加到窗口中。 m是PhoneWindowManager,控制启动窗口的添加、删除和修改。 在PhoneWindowManager中配置启动窗口,获取当前活动设置的主题和资源信息,在启动窗口中设置。 //phone window manager @ override public View addstarting window(I binder app token,String packageName,int theme,CompatibilityInfo compatInfo,Char sequence nonlocalized label,int label RES,int icon,int logo,int window flags,configuration override config){//如果(!SHOW _ STARTING _ ANIMATIONS){ return null;} WindowManager wm = nullView view = null//1.Get Context context,theme主题和标题Context context = mContext如果(主题!= context . getthemereid()| | label RES!= 0){ try { context = context . createpackagecontext(package name,0);context.setTheme(主题);} catch(包管理器。NameNotFundException e){//ignore } }//2。创建PhoneWindow以显示最终PhoneWindow Win = NewPhoneWindow(上下文);win . setisstartingwindow(true);//3.设置当前窗口类型和标志,这在源代码注释中有清楚的描述...win . settype(window manager . layout params . type _ application _ starting);win.setFlags(...);` ` ` ` ` view = win . getdecorview();//4.窗口管理器的绘制过程wm.addView(view,params);return view.getParent()!= null?视图:空;}如果theme和labelRes的值不为0,说明开发者已经指定了启动窗口的主题和标题,所以需要从当前要启动的活动中获取这些信息,并在启动窗口中设置。 和其他窗口一样,启动窗口需要通过PhoneWindow设置布局信息DecorView。 所以在上面的视觉优化中,设置闪屏图片主题的启动窗口显示的是图片内容。 启动窗口和普通窗口的区别在于它是一个假窗口,不需要触碰事件。最后会通过WindowManger的测量-布局-绘制过程显示启动窗口。最后,WindowManagerService将被请求在启动窗口中添加一个WindowState对象,该对象将真正向客户显示启动窗口并管理启动窗口。 关于WindowManager的addView过程的更多信息,请参考:https://blog.csdn.net/qian520ao/article/details/78657084's视图的工作流程概要。总结了应用程序的启动优化和启动窗口的源代码分析。在项目的开发中要知道为什么会发生,对源代码的分析有助于我们理解原理,处理问题的根源。 边肖在网上收集了一些先进的Android资料。请点击GitHub查看。希望对大家有帮助。收集这些材料并不容易。


  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【域名/主机/服务器|】qq邮箱提醒在哪里打开(2024-06-04 18:58)
【技术支持|常见问题】1556原创ng8文章搜索页面不齐(2024-05-01 14:43)
【技术支持|常见问题】1502企业站群-多域名跳转-多模板切换(2024-04-09 12:19)
【技术支持|常见问题】1126完美滑屏版视频只能显示10个(2024-03-29 13:37)
【技术支持|常见问题】响应式自适应代码(2024-03-24 14:23)
【技术支持|常见问题】1126完美滑屏版百度未授权使用地图api怎么办(2024-03-15 07:21)
【技术支持|常见问题】如何集成阿里通信短信接口(2024-02-19 21:48)
【技术支持|常见问题】算命网微信支付宝产品名称年份在哪修改?风水姻缘合婚配对_公司起名占卜八字算命算财运查吉凶源码(2024-01-07 12:27)
【域名/主机/服务器|】帝国CMS安装(2023-08-20 11:31)
【技术支持|常见问题】通过HTTPs测试Mozilla DNS {免费源码}(2022-11-04 10:37)

联系我们
Q Q:375457086
Q Q:526665408
电话:0755-84666665
微信:15999668636
联系客服
企业客服1 企业客服2 联系客服
86-755-84666665
手机版
手机版
扫一扫进手机版
返回顶部