Android Setting锁屏方式切换时卡顿问题

问题描述:设置->安全性和位置信息->屏幕锁定,快速切换锁定方式滑动到无,或者无到滑动后再点击菜单,卡顿4~5s。
对于性能方面的问题,一直觉得比较难搞,在拿到问题的时候,我们测试已经在原生机上对比测试过,也会有卡顿现象。但是是客户发现并提出的问题,还得搞。
首先打开systrace,我这里是用的ddms录制trace.html(具体方法csdn上很多),用chrom打开(文件被覆盖,没有截图了)systrace提供了一些UI Thread耗时cpu耗时等分析图,从图上分析可以看出,有很长一段时间,系统在进行GC,大约花费3~4s的时间,感觉可以查一下问题,从网上查询资料花了半天,知道是系统进行GC的时候是会阻塞当面界面的,表现上就是界面卡住了,但是GC是虚拟机系统行为,code无法控制,还得需要找源头,为何会有这么多垃圾需要回收。
下一步只好再打开著名的traceview工具,也是分析性能问题的好帮手。同样使用DDMS工具上集成的方式,我使用的是MTK release的工具GAT(虽然项目是高通项目~)首先我用traceView看了一下,traceview主要是看一些方法的耗时和调用情况,以及消耗cpu的状态,从函数方法的调用来看,耗时最高的就是主线程,达到了4.7秒,图形上看,似乎这个Binder操作耗费的时间有点高。
traceview
双击这一块看到信息,Binder操作的inc cpu time占用14%,但是incl Real Time是73%的时间,达到了5秒多,这种情况主要是因为可能CPU的上下文切换、阻塞、GC等原因造成,与systrace上看出的问题一致,如图:
在这里插入图片描述
下面再录制一份log,找关键字ActivityManager和Binder看看情况,找到如下log:

01-21 14:07:49.951 1109 1285 I ActivityManager: Displayed com.android.settings/.SubSettings: +5s544ms [aosp]

可见,这个subSetting花了5秒半,相当长,循着时间往前看5s,看看是否有什么蛛丝马迹,找到了binder出错的信息:

01-21 14:07:43.931 4218 4218 E ActivityThread: Activity com.android.settings.SubSettings has leaked ServiceConnection com.android.settings.password.ChooseLockGeneric$ChooseLockGenericFragment 1 @ 680 f 7 e 9 t h a t w a s o r i g i n a l l y b o u n d h e r e 01 − 2114 : 07 : 43.93142184218 E A c t i v i t y T h r e a d : a n d r o i d . a p p . S e r v i c e C o n n e c t i o n L e a k e d : A c t i v i t y c o m . a n d r o i d . s e t t i n g s . S u b S e t t i n g s h a s l e a k e d S e r v i c e C o n n e c t i o n c o m . a n d r o i d . s e t t i n g s . p a s s w o r d . C h o o s e L o c k G e n e r i c 1@680f7e9 that was originally bound here 01-21 14:07:43.931 4218 4218 E ActivityThread: android.app.ServiceConnectionLeaked: Activity com.android.settings.SubSettings has leaked ServiceConnection com.android.settings.password.ChooseLockGeneric 1@680f7e9thatwasoriginallyboundhere012114:07:43.93142184218EActivityThread:android.app.ServiceConnectionLeaked:Activitycom.android.settings.SubSettingshasleakedServiceConnectioncom.android.settings.password.ChooseLockGenericChooseLockGenericFragment 1 @ 680 f 7 e 9 t h a t w a s o r i g i n a l l y b o u n d h e r e 01 − 2114 : 07 : 43.93142184218 E A c t i v i t y T h r e a d : a t a n d r o i d . a p p . L o a d e d A p k 1@680f7e9 that was originally bound here 01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.LoadedApk 1@680f7e9thatwasoriginallyboundhere012114:07:43.93142184218EActivityThread:atandroid.app.LoadedApkServiceDispatcher.(LoadedApk.java:1532)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:1424)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1605)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.ContextImpl.bindService(ContextImpl.java:1557)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.content.ContextWrapper.bindService(ContextWrapper.java:684)
01-21 14:07:43.931 4218 4218 E ActivityThread: at com.android.settings.password.ChooseLockGeneric C h o o s e L o c k G e n e r i c F r a g m e n t . b i n d S e r v i c e ( C h o o s e L o c k G e n e r i c . j a v a : 297 ) 01 − 2114 : 07 : 43.93142184218 E A c t i v i t y T h r e a d : a t c o m . a n d r o i d . s e t t i n g s . p a s s w o r d . C h o o s e L o c k G e n e r i c ChooseLockGenericFragment.bindService(ChooseLockGeneric.java:297) 01-21 14:07:43.931 4218 4218 E ActivityThread: at com.android.settings.password.ChooseLockGeneric ChooseLockGenericFragment.bindService(ChooseLockGeneric.java:297)012114:07:43.93142184218EActivityThread:atcom.android.settings.password.ChooseLockGenericChooseLockGenericFragment.onCreate(ChooseLockGeneric.java:201)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.Fragment.performCreate(Fragment.java:2489)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1237)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2407)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2186)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2142)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2043)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:799)
01-21 14:07:43.931 4218 4218 E ActivityThread: at com.android.settings.SettingsActivity.switchToFragment(SettingsActivity.java:781)
01-21 14:07:43.931 4218 4218 E ActivityThread: at com.android.settings.SettingsActivity.launchSettingFragment(SettingsActivity.java:439)
01-21 14:07:43.931 4218 4218 E ActivityThread: at com.android.settings.SettingsActivity.onCreate(SettingsActivity.java:327)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.Activity.performCreate(Activity.java:7023)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.Activity.performCreate(Activity.java:7014)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2734)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2859)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.ActivityThread.-wrap11(Unknown Source:0)
01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.ActivityThread H . h a n d l e M e s s a g e ( A c t i v i t y T h r e a d . j a v a : 1592 ) 01 − 2114 : 07 : 43.93142184218 E A c t i v i t y T h r e a d : a t a n d r o i d . o s . H a n d l e r . d i s p a t c h M e s s a g e ( H a n d l e r . j a v a : 106 ) 01 − 2114 : 07 : 43.93142184218 E A c t i v i t y T h r e a d : a t a n d r o i d . o s . L o o p e r . l o o p ( L o o p e r . j a v a : 164 ) 01 − 2114 : 07 : 43.93142184218 E A c t i v i t y T h r e a d : a t a n d r o i d . a p p . A c t i v i t y T h r e a d . m a i n ( A c t i v i t y T h r e a d . j a v a : 6518 ) 01 − 2114 : 07 : 43.93142184218 E A c t i v i t y T h r e a d : a t j a v a . l a n g . r e f l e c t . M e t h o d . i n v o k e ( N a t i v e M e t h o d ) 01 − 2114 : 07 : 43.93142184218 E A c t i v i t y T h r e a d : a t c o m . a n d r o i d . i n t e r n a l . o s . R u n t i m e I n i t H.handleMessage(ActivityThread.java:1592) 01-21 14:07:43.931 4218 4218 E ActivityThread: at android.os.Handler.dispatchMessage(Handler.java:106) 01-21 14:07:43.931 4218 4218 E ActivityThread: at android.os.Looper.loop(Looper.java:164) 01-21 14:07:43.931 4218 4218 E ActivityThread: at android.app.ActivityThread.main(ActivityThread.java:6518) 01-21 14:07:43.931 4218 4218 E ActivityThread: at java.lang.reflect.Method.invoke(Native Method) 01-21 14:07:43.931 4218 4218 E ActivityThread: at com.android.internal.os.RuntimeInit H.handleMessage(ActivityThread.java:1592)012114:07:43.93142184218EActivityThread:atandroid.os.Handler.dispatchMessage(Handler.java:106)012114:07:43.93142184218EActivityThread:atandroid.os.Looper.loop(Looper.java:164)012114:07:43.93142184218EActivityThread:atandroid.app.ActivityThread.main(ActivityThread.java:6518)012114:07:43.93142184218EActivityThread:atjava.lang.reflect.Method.invoke(NativeMethod)012114:07:43.93142184218EActivityThread:atcom.android.internal.os.RuntimeInitMethodAndArgsCaller.run(RuntimeInit.java:438)
01-21 14:07:43.931 4218 4218 E ActivityThread: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
01-21 14:07:43.987 1109 3345 W ActivityManager: Unbind failed: could not find connection for android.os.BinderProxy@8d5f5b4

好巧,报错也是因为Binder没有unBinder成功,与traceview的Binder耗时,以及systrace的GC耗时的信息都有千丝万缕的关系,也许就是问题的所在,接下来就是解决这个错误,并验证的时刻。找到如下资料:

Google Android Issue中有这个缺陷,缺陷详细信息在这里(Google Android Issue 2483),
Using getApplicationContext().bindService instead of just bindService on your activity solves the problem as it is using the higher level application context.
先调用getApplicationContext()获取其所属的Activity的上下文环境才能正常bindService,
也就是在onCreate()方法中使用this.getApplicationContext().bindService([args…])就可以了,否则bindService将永远失败返回false。

那么就看log找到对应的地方,我们发现绑定binder的地方是用的getContext().Binder(xxxx),解绑的地方是用的getActivity().unBinder(xxx),我们通通换成getActivity().getApplicationContext().binder(xxx) (unBinder),编译push验证,查看log如下:

Line 2240: 01-21 15:29:12.629 1167 1325 I ActivityManager: Displayed com.android.settings/.SubSettings: +2s672ms [aosp]

成功优化了大约3秒的时间,虽然还感觉有卡顿,但是已经好很多,因为为了方便调试,编译的是userdebug版本,使用user版本后效果还有提升,算是能给客户一个交代了。完工!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Settings是一个应用程序,用于管理和配置Android设备的各种设置选项。它是通过在AndroidManifest.xml文件中声明相应的Activity和Intent过滤器来实现的。\[1\]通过使用"android.intent.action.MAIN"的action和"android.intent.category.DEFAULT"的category,Settings.APK默认从Settings这个Activity进入。而在Launcher进入时,启动的是Settings.java,由"android.intent.category.LAUNCHER"决定。\[1\] 如果我们想将Security设置项添加到shortcut列表,可以在androidmanifest.xml中声明Settings$SecuritySettingsActivity部分,并添加<category android:name="com.android.settings.SHORTCUT" />。\[2\] 当执行startActivity后,将启动SubSettings.java。这将再次执行SubSettings和PreferenceActivity的onCreate方法,但不会进入Settings的主界面,因为使用的intent对象不同。在onCreate函数中,initialFragment将被初始化为com.android.settings.DisplaySettings,然后进入switchToHeader(),最后通过transaction.replace(com.android.internal.R.id.prefs, f)将fragment显示出来。同时,其他view的visibility也会进行设置,以保证只显示prefs,如将com.android.internal.R.id.headers的visibility设置为VIEW.GONE。\[3\] 总结来说,Android Settings是一个用于管理和配置Android设备设置的应用程序,通过声明Activity和Intent过滤器来实现不同的功能和界面。 #### 引用[.reference_title] - *1* *2* *3* [Android Settings总结](https://blog.csdn.net/joychanger/article/details/51336527)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值