系列文章目录
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用
文章目录
- 系列文章目录
- 前言
- 一、业务耗时
- 1.登录Dialog优化
- 2.子线程更新通知栏
- 二、频繁调用
- 1.底部Tab资源初始化
- 三、Binder资源不足
- 1.运行时权限判断优化
- 2.Intent复用
- 总结
前言
一、业务耗时
1.登录Dialog优化
"main" prio=5 tid=1 Native
| group="main" sCount=1 dsCount=0 flags=1 obj=0x72cc6fb8 self=0xa2c84610
| sysTid=28496 nice=0 cgrp=default sched=1073741825/1 handle=0xaff39470
| state=S schedstat=( 217838418253 2300050047 386660 ) utm=18046 stm=3737 core=1 HZ=100
| stack=0xbe0f4000-0xbe0f6000 stackSize=8192KB
| held mutexes=
native: #00 pc 00034038 /apex/com.android.runtime/lib/bionic/libc.so (syscall+28)
native: #01 pc 00039149 /apex/com.android.runtime/lib/bionic/libc.so (__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+92)
native: #02 pc 0007ffe3 /apex/com.android.runtime/lib/bionic/libc.so (pthread_cond_wait+32)
native: #03 pc 0003d155 /system/lib/libc++.so (std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&)+8)
native: #04 pc 0003f019 /system/lib/libc++.so (std::__1::__assoc_sub_state::__sub_wait(std::__1::unique_lock<std::__1::mutex>&)+24)
native: #05 pc 0021b00d /system/lib/libhwui.so (android::uirenderer::renderthread::RenderProxy::RenderProxy(bool, android::uirenderer::RenderNode*, android::uirenderer::IContextFactory*)+452)
native: #06 pc 0020126f /system/lib/libhwui.so (android::android_view_ThreadedRenderer_createProxy(_JNIEnv*, _jobject*, unsigned char, unsigned char, long long)+58)
at android.graphics.HardwareRenderer.nCreateProxy(Native method)
at android.graphics.HardwareRenderer.<init>(HardwareRenderer.java:160)
at android.view.ThreadedRenderer.<init>(ThreadedRenderer.java:289)
at android.view.ThreadedRenderer.create(ThreadedRenderer.java:255)
at android.view.ViewRootImpl.enableHardwareAcceleration(ViewRootImpl.java:1398)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:1009)
- locked <0x0c5a9a6b> (a android.view.ViewRootImpl)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:409)
- locked <0x039fca61> (a java.lang.Object)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:109)
at android.app.Dialog.show(Dialog.java:384)
at com.xxx.util.SignupLoginDialog.buildDialog(:3)
at com.xxx.util.SignupLoginDialog.openRegisterLoginDialog(:5)
at com.xxx.kit.function.CustomCommentDialog.showLoginOrSignUp(:2)
at com.xxx.kit.function.CustomCommentDialog.showLoginOrSignUp(:1)
at com.xxx.ui.xx.room.VoiceRoomFragment.onClickVoiceRoomSeatsByViewer(:6)
at com.xxx.ui.xx.room.VoiceRoomFragment.onClickVoiceRoomSeats(:4)
at com.xxx.ui.xx.room.VoiceRoomFragment.lambda$init$9(:1)
at com.xxx.ui.xx.room.VoiceRoomFragment.lambda$init$9$VoiceRoomFragment(:-1)
at com.xxx.ui.xx.room.-$$Lambda$VoiceRoomFragment$ZS2IAg70OkVevpXcQJjytmKz_3w.clickVoiceRoomSeats(:-1)
at com.xxx.ui.xx.adapter.VoiceRoomSeatsAdapter.lambda$onBindViewHolder$1(:1)
at com.xxx.ui.xx.adapter.VoiceRoomSeatsAdapter.lambda$onBindViewHolder$1$VoiceRoomSeatsAdapter(:-1)
at com.xxx.ui.xx.adapter.-$$Lambda$VoiceRoomSeatsAdapter$-hYnXO7y6oji9WzyVYN0Z6bdivg.onClick(:-1)
at android.view.View.performClick(View.java:7465)
at android.view.View.performClickInternal(View.java:7438)
at android.view.View.access$3600(View.java:813)
at android.view.View$PerformClick.run(View.java:28505)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:268)
at android.app.ActivityThread.main(ActivityThread.java:7963)
at java.lang.reflect.Method.invoke(Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:627)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:997)
日志可看出是SignupLoginDialog的问题,结合业务代码查看:
public SignupLoginDialog(Activity context, int sourceFrom, LocalLoginParams params) {
...
initFaceBookAuth(activity, findViewById(R.id.ivFacebook));
initGoogleAuth(activity, findViewById(R.id.llGoogle));
initTwitterAuth(activity, findViewById(R.id.ivTiwtter));
...
}
可以看到FaceBook/Google/Twitter等三方账号在Dialog初始化的时候同时进行了初始化,较为耗时。
修改:抽取出各个三方登录平台初始化,用到时再进行初始化。
2.子线程更新通知栏
"main" tid=1 Runnable
at android.os.Bundle.<init> (Bundle.java:67)
at androidx.core.app.NotificationCompatBuilder.<init> (NotificationCompatBuilder.java:61)
at androidx.core.app.NotificationCompat$Builder.build (NotificationCompat.java:2346)
at com.xxx.biz.remote.XxNotification.innerDisplayNotifcation (XxNotification.java:498)
at com.xxx.biz.remote.XxNotification.displayNotifcation (XxNotification.java:262)
at com.xxx.biz.remote.XxNotification.displayNotifcation (XxNotification.java:268)
at com.xxx.xxx.service.XxService$10.onNext (XxService.java:925)
at com.xxx.xxx.service.XxService$10.onNext (XxService.java:913)
at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal (ObservableObserveOn.java:201)
at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run (ObservableObserveOn.java:255)
at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run (HandlerScheduler.java:124)
at android.os.Handler.handleCallback (Handler.java:873)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loop (Looper.java:193)
at android.app.ActivityThread.main (ActivityThread.java:6758)
at java.lang.reflect.Method.invoke (Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:497)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:912)
通过日志定位,查看innerDisplayNotifcation方法,内部有大量Notification相关的设置,大小图标适配等,且与业务高度耦合。
尝试了以下方案:
1.innerDisplayNotifcation方法拆分。
2.方法调用频率降低,监听通知栏下滑时候再去更新–>onWindowFocusChanged(无法准确获取通知栏下拉监听)
3.子线程更新通知栏
最终将innerDisplayNotifcation方法放入子线程执行,进行通知栏更新,可以彻底解决该ANR问题。
二、频繁调用
1.底部Tab资源初始化
"main" tid=1 Native
#00 pc 0x0000000000019d1c /system/lib/libc.so (syscall+28)
#01 pc 0x00000000000a6b63 /system/lib/libart.so (art::ConditionVariable::WaitHoldingLocks(art::Thread*)+78)
#02 pc 0x00000000003d490f /system/lib/libart.so (art::GoToRunnable(art::Thread*) (.llvm.<US_SOCIAL_SECURITY_NUMBER>)+314)
#03 pc 0x00000000003d47ad /system/lib/libart.so (art::JniMethodEnd(unsigned int, art::Thread*)+8)
at android.content.res.AssetManager.nativeOpenNonAsset (Native method)
at android.content.res.AssetManager.openNonAsset (AssetManager.java:878)
at android.content.res.ResourcesImpl.loadDrawableForCookie (ResourcesImpl.java:858)
at android.content.res.ResourcesImpl.loadDrawable (ResourcesImpl.java:648)
at android.content.res.Resources.getDrawableForDensity (Resources.java:888)
at android.content.res.Resources.getDrawable (Resources.java:827)
at android.content.res.Resources.getDrawable (Resources.java:802)
at com.xxx.kit.widget.HomeBottomTabLayout.setDefaultValue (HomeBottomTabLayout.java:60)
at com.xxx.ui.home.fragment.HomeTabFragment.onCreateView (HomeTabFragment.java:91)
at androidx.fragment.app.Fragment.performCreateView (Fragment.java:2963)
at androidx.fragment.app.FragmentStateManager.createView (FragmentStateManager.java:518)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState (FragmentStateManager.java:282)
at androidx.fragment.app.FragmentManager.executeOpsTogether (FragmentManager.java:2189)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute (FragmentManager.java:2100)
at androidx.fragment.app.FragmentManager.execPendingActions (FragmentManager.java:2002)
at androidx.fragment.app.FragmentManager.executePendingTransactions (FragmentManager.java:600)
at com.xxx.ui.main.MainActivity.replaceFragment (MainActivity.java:1289)
at com.xxx.ui.main.MainActivity.replaceMainActivityFragment (MainActivity.java:716)
at com.xxx.ui.main.MainActivity.access$000 (MainActivity.java:256)
at com.xxx.ui.main.MainActivity$ReleaseFragmentRunnable.run (MainActivity.java:704)
at android.os.Handler.handleCallback (Handler.java:873)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loop (Looper.java:193)
at android.app.ActivityThread.main (ActivityThread.java:6710)
at java.lang.reflect.Method.invoke (Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:497)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:911)
HomeBottomTabLayout.setDefaultValue这个方法在onresume调用,频率高。在view的构造方法把getResources().getDrawable先取出来,setDefaultValue 方法直接给数组设置drawable。
修改:
三、Binder资源不足
1.运行时权限判断优化
"main" tid=1 Native
#00 pc 0x000000000005ddec /apex/com.android.runtime/lib/bionic/libc.so (syscall+28)
#01 pc 0x0000000000130dc9 /apex/com.android.art/lib/libart.so (art::ConditionVariable::WaitHoldingLocks(art::Thread*)+88)
#02 pc 0x00000000004d8c23 /apex/com.android.art/lib/libart.so (art::GoToRunnable(art::Thread*)+342)
#03 pc 0x00000000004d8aa5 /apex/com.android.art/lib/libart.so (art::JniMethodEnd(unsigned int, art::Thread*)+8)
at android.os.BinderProxy.transactNative (BinderProxy.java)
at android.os.BinderProxy.transact (BinderProxy.java:540)
at android.os.storage.IStorageManager$Stub$Proxy.getVolumeList (IStorageManager.java:1610)
at android.os.storage.StorageManager.getVolumeList (StorageManager.java:1381)
at android.os.Environment$UserEnvironment.getExternalDirs (Environment.java:160)
at android.os.Environment.isExternalStorageLegacy (Environment.java:1262)
at com.xxx.storage.cache.ScopeStorageUtils.isScopeStorageEnabled (ScopeStorageUtils.java:31)
at com.xxx.util.PermissionUtil.getExternalStoragePermissionStr (PermissionUtil.java:22)
at com.xxx.common.base.XxxApplicationInitor.checkPermission (MusicApplicationInitor.java:688)
at com.xxx.ui.main.MainActivity.onResume (MainActivity.java:2196)
at android.app.Instrumentation.callActivityOnResume (Instrumentation.java:1456)
at android.app.Activity.performResume (Activity.java:8135)
at android.app.ActivityThread.performResumeActivity (ActivityThread.java:4481)
at android.app.ActivityThread.handleResumeActivity (ActivityThread.java:4523)
at android.app.servertransaction.ResumeActivityItem.execute (ResumeActivityItem.java:52)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:176)
at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2116)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:223)
at android.app.ActivityThread.main (ActivityThread.java:7723)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:612)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:997)
运行时权限频繁判定频繁获取,Binder资源不足导致,通过存储权限数组为全局变量以减少通讯。修改:
XxxApplicationInitor.checkPermission
public static List<String> checkPermission() {
List<String> strs = new ArrayList<>(2);
if (XxApplication.getApplication() == null) {
return strs;
}
if (ContextCompat.checkSelfPermission(context,
PermissionUtil.getExternalStoragePermissionStr()) != PackageManager.PERMISSION_GRANTED) {
strs.add(PermissionUtil.getExternalStoragePermissionStr());
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
strs.add(Manifest.permission.READ_PHONE_STATE);
}
}
return strs;
}
2.Intent复用
"main" tid=1 Native
#00 pc 0x00000000000d7b74 /apex/com.android.runtime/lib64/bionic/libc.so (__ioctl+4)
#01 pc 0x0000000000093f70 /apex/com.android.runtime/lib64/bionic/libc.so (ioctl+160)
#02 pc 0x0000000000051c7c /system/lib64/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+300)
#03 pc 0x0000000000052c8c /system/lib64/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+60)
#04 pc 0x00000000000529f4 /system/lib64/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+188)
#05 pc 0x000000000004b0b0 /system/lib64/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+152)
#06 pc 0x00000000001270c0 /system/lib64/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)+152)
at android.os.BinderProxy.transactNative (Native method)
at android.os.BinderProxy.transact (BinderProxy.java:565)
at android.app.IActivityManager$Stub$Proxy.getIntentSenderWithFeature (IActivityManager.java:7555)
at android.app.PendingIntent.getBroadcastAsUser (PendingIntent.java:578)
at android.app.PendingIntent.getBroadcast (PendingIntent.java:561)
at com.xxx.util.Utils.getBroadcast (Utils.java:1126)
at com.xxx.biz.download.utils.DownloadNotification.updateDownloadingNotification (DownloadNotification.java:168)
at com.xxx.biz.download.utils.DownloadController$DownloadCallback.onProgress (DownloadController.java:824)
at com.xxx.common.network.download.Downloader$1$1.accept (Downloader.java:99)
at com.xxx.common.network.download.Downloader$1$1.accept (Downloader.java:94)
at io.reactivex.internal.observers.LambdaObserver.onNext (LambdaObserver.java:63)
at io.reactivex.observers.SerializedObserver.onNext (SerializedObserver.java:111)
at io.reactivex.internal.operators.observable.ObservableDebounceTimed$DebounceTimedObserver.emit (ObservableDebounceTimed.java:143)
at io.reactivex.internal.operators.observable.ObservableDebounceTimed$DebounceEmitter.run (ObservableDebounceTimed.java:168)
at io.reactivex.internal.operators.observable.ObservableDebounceTimed$DebounceTimedObserver.onComplete (ObservableDebounceTimed.java:124)
at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.checkTerminated (ObservableObserveOn.java:287)
at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal (ObservableObserveOn.java:193)
at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run (ObservableObserveOn.java:255)
at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run (HandlerScheduler.java:124)
at android.os.Handler.handleCallback (Handler.java:938)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loop (Looper.java:257)
at android.app.ActivityThread.main (ActivityThread.java:8220)
at java.lang.reflect.Method.invoke (Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:626)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1015)
DownloadController$DownloadCallback.onProgress
class DownloadCallback implements DownloadListener {
public void onProgress(long downloadedSize, long totalSize) {
...
DownloadNotification.updateDownloadingNotification(downloadFile.getName(), (int) downloadedSize, (int) totalSize);
}
}
DownloadNotification.updateDownloadingNotification
public static void updateDownloadingNotification(String name, int progress, int total) {
Intent intent = new Intent(ConstantUtil.notification_broadcast_action_to_download);
intent.putExtra(IntentHandler.INTENT_TO_ACTIVITY, CommentString.DOWNLOAD_QUEUE_ACTIVITY);
PendingIntent pendingIntent = Utils.getBroadcast(MusicApplication.getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
updateDownloading(name, progress, total, pendingIntent);
}
Utils.getBroadcast
public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags){
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
//适配 Android S
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE);
} else {
return PendingIntent.getBroadcast(context, requestCode, intent, flags);
}
}
onProgress为下载进度回调,调用比较频繁,导致低端机Binder资源不足,可以修改复用updateDownloadingNotification方法中的intent:
private static PendingIntent mNotificationContentIntent = getContentPendingIntent();
public static PendingIntent getContentPendingIntent() {
Intent intent = new Intent(ConstantUtil.notification_broadcast_action_to_download);
intent.putExtra(IntentHandler.INTENT_TO_ACTIVITY, CommentString.DOWNLOAD_QUEUE_ACTIVITY);
PendingIntent pendingIntent = Utils.getBroadcast(MusicApplication.getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
public static void updateDownloadingNotification(String name, int progress, int total) {
Intent intent = new Intent(ConstantUtil.notification_broadcast_action_to_download);
intent.putExtra(IntentHandler.INTENT_TO_ACTIVITY, CommentString.DOWNLOAD_QUEUE_ACTIVITY);
updateDownloading(name, progress, total, mNotificationContentIntent);//意图复用
}