【ANDROID游戏开发十九】(必看篇)SURFACEVIEW运行机制详解—剖析BACK与HOME按键及切入后台等异常处理!

简介:
本站文章均为  李华明Himi  原创,转载务必在明显处注明: 

转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/android-game/346.html


在这里先向各位童鞋道个歉!我解释下:当我在给大家讲解的时候会附带上源码,可是这个源码是演示代码,为了让大家看的清楚,所以我会尽可能把一些与其无关的删掉,但是发现演示代码还是被一些童鞋们效仿,导致不少童鞋问我为什么程序执行后切入后台重新进入会报异常的问题!(这里我就全面讲解下运行机制,希望以后大家有类似问题自己就能解决了哈~)

                                                    切入后台操作比如点击HOME按键,点击返回按键...

 那么重新进入程序报异常主要Surfaceiew 有两点会报异常:

第一:提交画布异常!如下图(模拟器错误提示,以及Logcat Detail)

解决代码:

先看备注1这里,之前的文章中我给大家解释过为什么要把 sfh.unlockCanvasAndPost(canvas); 写在finally中,主要是为了保证能正常的提交画

布.今天主要说说备注2这里一定要判定下canvas是否为空,因为当程序切入后台的时候,canvas是获取不到的!那么canvas一旦为空,提交画

布这里就会出现参数异常的错误!

下面来说另外一种情况:线程启动异常!如下图(模拟器错误提示,以及Logcat Detail)

 

这种异常只是在当你程序运行期间点击Home按钮后再次进入程序的时候报的异常,异常说咱们的线程已经启动!为什么返回按钮就没事?

OK,下面我们就要来先详细讲解一下Android中Back和Home按键的机制!然后分析问题,并且解决问题!

先看下面MySurfaceViewAnimation.java的类中的代码:

以上是我们常用的自定义SurfaceView,并且使用Runnable接口老框架了不多说了,其中我在本类的构造、创建、状态改变、消亡函数都加上打印!

OK,下面看第一张图:(刚运行程序)

 

上图的左边部分是Dubug!这里显示我们有一条线程在运行,名字叫”himi_Thread_one”;

上图的左边部分是LogCat日志!大家很清晰的看到,当第一次进入程序的时候,会先进入view构造函数、然后是创建view、然后是view状态改变、OK,这个大家都知道!

下面我来点击Home(手机上的小房子)按键!这时程序处于后台!然后重新进入程序的过程!

 

上图可以看出我们的线程还是一条、这里主要观察从点击home到再次进入程序的过程:(过程如下):

点击home 调用了view销毁、然后进入程序会先进入view创建,最后是view状态改变!

上面的过程很容易理解,重要的角色上场了~Back 按钮!点我点击Back按钮看看发生了什么!

 

先看左边的Debug一栏,多了一条线程! 看LogCat发现比点击Home按键多调用了一次构造函数!

好了,从我们测试的程序来看,无疑,点击Home 和 点击 Back按钮再次进入程序的时候,步骤是不一样的,线程数量也变了!

     那么这里就能解释为什么我们点击Back按钮不异常、点击Home会异常了!

     原因:因为点击Back按钮再次进入程序的时候先进入的是view构造函数里,那么就是说这里又new了一个线程出来,并启动!那么而我们点击Home却不一样了,因为点击home之后再次进入程序不会进入构造函数,而是直接进入了view创建这个函数,而在view创建这个函数中我们有个启动线程的操作,其实第一次启动程序的线程还在运行,so~这里就一定异常了,说线程已经启动!

 

有些童鞋会问,我们为何不把th = new Thread(this, “himi_Thread_one”);放在view创建函数中不就好了??!!

  没错,可以!但是当你反复几次之后你发现你的程序中会多出很多条进程!(如下图)

虽然可以避免出现线程已经启动的异常,很明显这不是我们想要的结果!

那么下面给大家介绍最合适的解决方案:

修改MySurfaceViewAnimation.java

这里修改的地方有以下几点:

1. 我们都知道一个线程启动后,只要run方法执行结束,线程就销毁了,所以我增加了一个布尔值的成员变量 himi(备注1),这里可以控制我们的线程消亡的一个开关!(备注4

2.在启动线程之前,设置这个布尔值为ture,让线程一直运行.

3.在view销毁时,设置这个布尔值为false,销毁当前线程!(备注3

OK,这里图和解释够详细了,希望大家以后真正开发一款游戏的时候,一定要严谨代码,不要留有后患哈~

 

相关文章
|
6月前
|
Java API 调度
Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播
Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播
321 0
|
3月前
|
编解码 网络协议 Android开发
Android平台GB28181设备接入模块实现后台service按需回传摄像头数据到国标平台侧
我们在做Android平台GB28181设备对接模块的时候,遇到这样的技术需求,开发者希望能以后台服务的形式运行程序,国标平台侧没有视频回传请求的时候,仅保持信令链接,有发起视频回传请求或语音广播时,打开摄像头,并实时回传音视频数据或接收处理国标平台侧发过来的语音广播数据。
|
3月前
|
Android开发 开发者 Kotlin
Android 多进程情况下判断应用是否处于前台或者后台
本文介绍在多进程环境下判断Android应用前后台状态的方法。通过`ActivityManager`和服务信息`RunningAppProcessInfo`可有效检测应用状态,优化资源使用。提供Kotlin代码示例,帮助开发者轻松集成。
266 8
|
4月前
|
监控 Android开发 开发者
Android经典面试题之实战经验分享:如何简单实现App的前后台监听判断
本文介绍在Android中判断应用前后台状态的两种方法:`ActivityLifecycleCallbacks`和`ProcessLifecycleOwner`。前者提供精细控制,适用于需针对每个Activity处理的场景;后者简化前后台检测,适用于多数应用。两者各有优劣:`ActivityLifecycleCallbacks`更精确但复杂度高;`ProcessLifecycleOwner`更简便但可能在极端场景下略有差异。根据应用需求选择合适方法。
39 2
|
5月前
|
Android开发
技术经验分享:Android前后台切换的监听
技术经验分享:Android前后台切换的监听
85 2
|
6月前
|
缓存 算法 Java
Linux内核新特性年终大盘点-安卓杀后台现象减少的背后功臣MGLRU算法简介
MGLRU是一种新型内存管理算法,它的出现是为了弥补传统LRU(Least Recently Used)和LFU(Least Frequently Used)算法在缓存替换选择上的不足,LRU和LFU的共同缺点就是在做内存页面替换时,只考虑内存页面在最近一段时间内被访问的次数和最后一次的访问时间,但是一个页面的最近访问次数少或者最近一次的访问时间较早,可能仅仅是因为这个内存页面新近才被创建,属于刚刚完成初始化的年代代页面,它的频繁访问往往会出现在初始化之后的一段时间里,那么这时候就把这种年轻代的页面迁移出去
|
安全 Java Android开发
Android 中AsyncTask后台线程,异步任务的理解
Android 中AsyncTask后台线程,异步任务的理解
155 0
|
Android开发
Android中保存当前按钮的状态 按back键返回之后再次进入没有改变
Android中保存当前按钮的状态 按back键返回之后再次进入没有改变
66 0
|
6月前
|
存储 移动开发 JavaScript
【原生】sd.js帮助您简化繁重的获取数据、存储数据(CRUD)骚操作(吐槽~在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据)
【原生】sd.js帮助您简化繁重的获取数据、存储数据(CRUD)骚操作(吐槽~在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据)
|
Android开发
Android JetPack组件之ViewModel状态的保存(程序在后台被系统杀死数据也存活)
Android JetPack组件之ViewModel状态的保存(程序在后台被系统杀死数据也存活)
152 0