android开发-bug记录

2022.01.10

正式接触android开发刚三四个月,记录一下三个第一次遇到的bug

自定义的圆角控件加载图片导致OOM

java.lang.OutOfMemoryError: Failed to allocate a 373980 byte allocation with 288904 free bytes and 282KB until OOM

// at dalvik.system.VMRuntime.newNonMovableArray(Native Method) // at android.graphics.Bitmap.nativeCreate(Native Method) // at android.graphics.Bitmap.createBitmap(Bitmap.java:879) // at android.graphics.Bitmap.createBitmap(Bitmap.java:856) // at android.graphics.Bitmap.createBitmap(Bitmap.java:776) // at com.discovery.modulehome.XCRoundRectImageView.getScaleBitmap(XCRoundRectImageView.java:221) // at com.discovery.modulehome.XCRoundRectImageView.onDraw(XCRoundRectImageView.java:92) // at android.view.View.draw(View.java:17320) // at android.view.View.updateDisplayListIfDirty(View.java:16259) // at android.view.View.draw(View.java:17070) // at android.view.ViewGroup.drawChild(ViewGroup.java:3892) // at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3678) // at android.view.View.draw(View.java:17332) // at android.view.View.updateDisplayListIfDirty(View.java:16259) // at android.view.View.draw(View.java:17070) // at android.view.ViewGroup.drawChild(ViewGroup.java:3892) // at androidx.recyclerview.widget.RecyclerView.drawChild(RecyclerView.java:5204) // at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3678) // at android.view.View.draw(View.java:17332) // at androidx.recyclerview.widget.RecyclerView.draw(RecyclerView.java:4603) // at android.view.View.updateDisplayListIfDirty(View.java:16259) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3876) // at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3856) // at android.view.View.updateDisplayListIfDirty(View.java:16213) // at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:661) // at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:667) // at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:775) // at android.view.ViewRootImpl.draw(ViewRootImpl.java:3188) // at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2981) // at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2569) // at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1462) // at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6965) // at android.view.Choreographer$CallbackRecord.run(Choreographer.java:907) // at android.view.Choreographer.doCallbacks(Choreographer.java:709) // at android.view.Choreographer.doFrame(Choreographer.java:644) // at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:893) // at android.os.Handler.handleCallback(Handler.java:836) // at android.os.Handler.dispatchMessage(Handler.java:103) // at android.os.Looper.loop(Looper.java:203) // at android.app.ActivityThread.main(ActivityThread.java:6251) // at java.lang.reflect.Method.invoke(Native Method) // at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063) // at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)

解:

根据网络上别人的经验,确认是在列表中上拉加载很多数据的时候,由于列表中的item含有一个自定义的圆角图片(继承ImageView的自定义圆角控件)导致的。

解决方式:需要在清单文件的application中加上下面两行代码:

 android:largeHeap="true"
 android:hardwareAccelerated="false"

android:largeHeap

在manifest中设置了 largeHeap=true之后,可以使用最大内存值。 设置largeHeap的确可以增加内存的申请量。但不是系统有多少内存就可以申请多少,而是由dalvik.vm.heapsize限制。 但是作为程序员的我们应该努力减少内存的使用,尽量想回收和复用的方法,而不是想方设法增大内存。当内存很大的时候,每次gc的时间也会长一些,性能会下降的。

android:hardwareAccelerated

通过网络得知:从Android3.0 (API level11)开始,Android的2D显示管道被被设计得更加支持硬加速了。硬加速使用GPU承担了所有在View的canvas上执行的绘制操作。启用硬加速最简单的的方法是对整个应用启用硬件速。如果应用只使用标准的view和Drawable,全局启用硬加速将不会带来任何负面影响。然而,因为硬加速不是被所有的2D绘制所支持,所以启用它时可能对自定义绘制产生影响。出现的问题经常是不可见的,也可能是异常,或错误地显示了像素。

而我这儿因为使用了自定义视频控件,添加了上面两个属性导致视频一致未准备好surface。尝试在AndroidManifest.xml中,用android:replace去覆盖属性值,但是无效(也有可能我使用的方式不太对,小白菜无奈..)。最后还是把所有使用了自定义的圆角图片控件的地方,换成通过继承Gilde的自定义对象,在java代码中动态加载图片切圆角。然后就不报这个bug了,视频也正常。

终:

与视频的绘制冲突,填上会导致视频surface一直未准备好

还是换掉自定义控件去解决。

弹窗导致IllegalStateException:报not associated with a fragment manager.错误

 CRASH: com.discovery.home.launcher.fj01 (pid 2999) // Short Msg: java.lang.IllegalStateException // Long Msg: java.lang.IllegalStateException: Fragment SYDialog{7b91deb (f60f3e52-b3e8-49f7-bcaf-13b4f6dd5700)} not associated with a fragment manager.

// Build Label: alps/full_fj01/fj01:7.0/NRD90M/1641551929:user/test-keys // Build Changelist: 1641551929 // Build Time: 1641551927000 // java.lang.IllegalStateException: Fragment SYDialog{7b91deb (f60f3e52-b3e8-49f7-bcaf-13b4f6dd5700)} not associated with a fragment manager. // at androidx.fragment.app.Fragment.requireFragmentManager(Fragment.java:910) // at androidx.fragment.app.DialogFragment.dismissInternal(DialogFragment.java:245) // at androidx.fragment.app.DialogFragment.dismissAllowingStateLoss(DialogFragment.java:212) // at com.discovery.modulehome.first_level.HomeWorkFragment.initTime(HomeWorkFragment.java:840) // at com.discovery.modulehome.first_level.HomeWorkFragment.access$3300(HomeWorkFragment.java:63) // at com.discovery.modulehome.first_level.HomeWorkFragment$1.handleMessage(HomeWorkFragment.java:522) // at android.os.Handler.dispatchMessage(Handler.java:110) // at android.os.Looper.loop(Looper.java:203) // at android.app.ActivityThread.main(ActivityThread.java:6251) // at java.lang.reflect.Method.invoke(Native Method) // at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063) // at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)

解:SYDialog是自定义的弹窗,是前辈写的通用工具,继承了DialogFragment。

dismiss()方法会调用dismissInternal方法,dismissInternal方法中需要获取mFragmentManager,如果为null就会抛出异常。在调用DialogFragment的时候需要传入一个FragmentMananger或是一个FragmentTransaction,并且把自身add到FragmentTransaction中,这时DialogFragment的mFragmentManager就被赋值了

根据网络的经验,和自己所做项目的特点,确认是fragment还没有初始化好,传入的getFragmentManager()值为null所导致。

解决方法: 避免在没有DialogFramgent没有show过的情况下调用dismiss 或是重写dismiss方法,手动判断在mFragmentManager不为null时才dismiss。所以添加了判空保护。

Glide加载图片时界面分离UI,导致NullPointerException

Short Msg: java.lang.NullPointerException // Long Msg: java.lang.NullPointerException: You cannot start a load on a not yet attached View or a Fragment where getActivity() returns null (which usually occurs when getActivity() is called before the Fragment is attached or after the Fragment is destroyed).

// Build Label: alps/full_fj01/fj01:7.0/NRD90M/1641551929:user/test-keys // Build Changelist: 1641551929 // Build Time: 1641551927000 // java.lang.NullPointerException: You cannot start a load on a not yet attached View or a Fragment where getActivity() returns null (which usually occurs when getActivity() is called before the Fragment is attached or after the Fragment is destroyed). // at com.bumptech.glide.util.Preconditions.checkNotNull(Preconditions.java:29) // at com.bumptech.glide.Glide.getRetriever(Glide.java:769) // at com.bumptech.glide.Glide.with(Glide.java:838) // at com.discovery.librarybase.imageloader.glide.GlideLoader.request(GlideLoader.java:28) // at com.discovery.librarybase.imageloader.ImageLoaderConfig.request(ImageLoaderConfig.java:37) // at com.discovery.librarybase.imageloader.ImageLoaderConfig$Builder.into(ImageLoaderConfig.java:109) // at com.test.moduleuser.fragment.UserCenterFragment.setHeadPicture(UserCenterFragment.java:156) // at com.test.moduleuser.fragment.UserCenterFragment.access$500(UserCenterFragment.java:36) // at com.test.moduleuser.fragment.UserCenterFragment$2.handleMessage(UserCenterFragment.java:76) // at android.os.Handler.dispatchMessage(Handler.java:110) // at android.os.Looper.loop(Looper.java:203) // at android.app.ActivityThread.main(ActivityThread.java:6251) // at java.lang.reflect.Method.invoke(Native Method) // at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063) // at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)

解:

Glide加载图片报错,可能是activity被销毁,而getContext()传入了空值导致的。我的页面都是fragment,加载前使用this.isDetached()判断页面是否分离ui。

希望自己日益精进。

2022.01.11

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Android Studio是一款用于Android手机应用开发的集成开发环境,它提供了丰富的开发工具和库,帮助开发者构建出功能丰富、稳定可靠的手机应用程序。那么如果要用Android Studio开发手机银行应用程序,需要以下几个步骤: 1. 确定功能需求:作为手机银行应用,功能非常重要。需要确定用户能够进行哪些操作,比如账户查询、转账、支付等。同时要考虑到安全性和稳定性,确保用户信息的安全性和交易的准确性。 2. 设计界面:在Android Studio中,可以使用自带的界面设计器或者手写代码来设计应用程序的界面。界面设计应该简洁美观,易用性要强,同时要考虑不同屏幕大小和分辨率的适配。 3. 数据库设计:手机银行应用需要管理用户信息和交易记录等数据,所以需要合适的数据库来存储这些信息。可以使用SQLite或者其他合适的数据库技术进行数据存储和管理。 4. 开发业务逻辑:根据需求,在Android Studio中实现业务逻辑,比如账户查询、转账和支付等功能。开发者可以使用Java或者Kotlin等编程语言来实现这些功能,并通过调用接口或者API与后台进行数据交互和处理。 5. 测试与调试:在开发过程中,要不断进行测试与调试,确保应用程序的稳定性和功能正常运行。Android Studio提供了强大的调试工具,方便开发者进行代码的调试和错误的修复。 6. 发布与更新:开发完成后,可以通过Android Studio将应用程序打包成APK文件,并发布到Google Play等应用商店供用户下载和使用。同时,还需要定期对应用程序进行更新和优化,修复bug和添加新的功能。 通过以上一系列的步骤,使用Android Studio开发手机银行应用程序将变得更加容易和高效。当然,开发过程中也需要不断学习和提升自己的编程能力,以及关注安全性和用户体验等因素,才能开发出高质量的手机银行应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值