当前位置:  编程技术>移动开发
本页文章导读:
    ▪关于Handler二三事(下)        关于Handler二三事(上) 一直以来,Handler于我而言都是难以形容的大麻烦。姑且不论线程通信一二三,就算是如何利用Handler来实现各项业务间消息传输,我也只能粗浅的说说如何跟踪消息而.........
    ▪ unity3d中的坑和好决方案        unity3d中的坑和 unity3d中的坑和      unity3d是一个很牛x的引擎,当然其也有一些东西是不太好或者说不习惯的,下面列举一些: 1、制作特效时,使用animation记录的位置是相对位置,如果直接.........
    ▪ 调用service静态方法抛RuntimeException有关问题       调用service静态方法抛RuntimeException问题     假设有一个service类是 AbcSvr在其内有一个static方法供外调用启动自己。 public static void startAbcSvr(Context ctx ) { ctx.startService(new Intent(ctx, AbcSvr.cl.........

[1]关于Handler二三事(下)
    来源: 互联网  发布时间: 2014-02-18
关于Handler二三事(上)

 一直以来,Handler于我而言都是难以形容的大麻烦。姑且不论线程通信一二三,就算是如何利用Handler来实现各项业务间消息传输,我也只能粗浅的说说如何跟踪消息而已。

跟它较劲了很久,零零碎碎总结了不少,总算是明白了些。记录下来权当作经验与各位分享。

 

我理解的Handler回调

先不说Handler,单问回调是什么,引用万能的wikipedia大神的话是这样的:

In computer programming, a callback is a piece of executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at someconvenient time. The invocation may be immediate as in a synchronous callback or it might happen at later time, asin an asynchronous callback.

我不知道诸位对它的解释是否满意,反正对我来说,说了跟没说一样。我理解回调的意义,知道回调的目的……但是,我不知道android Activity代码中一串串的onXXXX究竟是怎么来的!

这也许就是跨行从业的悲剧,一直学嵌入式硬件的我拼命阅读理解该死的底层代码,内核函数,仍然无法弄明白这个回调究竟是怎么起作用的,甚至怎么用都不明白。

直到有一天,我看到了这段话:

As your activity enters the paused state, thesystem calls theonPause() method on your Activity, which allows you to stopongoing actions that should not continue while paused (such as a video) orpersist any information that should be permanently saved in case the usercontinues to leave your app.

我终于有了那么点开窍,回调机制不就是披着软件马甲的硬件中断吗?

不知道在座各位是否了解嵌入式硬件中断,不过我知道做过单片机、dsp的同学肯定明白。所谓的中断,简单地讲就是当相应的中断源产生中断后,CPU会做现场保护,然后把PC指针跳进事先写好的中断服务程序中执行中断服务内容,执行完后CPU再恢复现场,接着该干嘛干嘛。

我这么说各位是否能看出来,这货活脱脱就是回调啊(当然肯定有不同的地方,但LZ就是这么理解的)!某个事件源引起了系统响应,进而调用相应的回调函数来实现该事件源的处理内容,从而完成了“事件响应”的处理。


我可以不去管系统是如何产生和触发相应的事件源的,虽然在设计硬件时我需要区分中断是硬中断还是软中断,中断向量表是怎么写的,等等等等。但是这里我可以不管你,我只需要知道硬件层面有相应的事件源消息产生了。

我在意的是,什么样的事件源与什么样的回调函数挂钩。简单地说,我需要知道什么事件源导致回调onCreate方法,什么事件源导致回调onClick方法。

相应的,我的工作,简单的说就是编写对应事件源下的中断服务程序(回调函数)了。我知道按下Activity上的一个虚拟Button,系统应该进行某些动作(譬如弹出个菜单,拨出个电话等),那么我只需要详细的描述onClick这个回调就可以了(当然,还有一些其他的配置代码需要另行编写)。

这个理解也许还不是那么恰当,但对目前的我来说,确实清楚了android代码架构和过去过程式编码的一些区别——android代码恐怕把很多设计底层的内容都隐藏了,暴露给程序员的,更多的是一些工具方法,其实从某种意义上说,所谓的编程倒像是在原有框架上一点点补足具体实现的内容。

而我之前难以理解的,其实是回调的实现机制而不是回调实现的具体内容了。


Thread、Handler、Looper以及Message

如果上面关于回调的内容讲的还算明白,请列位接着看这四个好基友的故事。

前文书说了,我一直维护framework侧代码,Activity什么的写的真心不多。那么在framework侧为什么会说到回调呢?

这是因为万恶的HandleMessage随处都在啊!

   /**
    * When overridden the derived class needs to call
    * super.handleMessage(msg) so this method has a
    * a chance to process the message.
    *
    * @param msg
    */
   @Override
   public void handleMessage(Message msg) {
       AsyncResult ar;
…
}

老大说“……喏,记得把这几个消息回调实现了,然后看一下log成功没有”

我:“#¥%@……”

 

要说这四个好基友的关系,就需要理顺他们之间混乱的关系。

先把结论抛出来,我再慢慢的细说内容吧:

所谓的Handle-Message机制,与其说是某种复杂的消息处理机制,不如把它看成送快递的。打了收件人(target)标记的快递(message)被扔到一台不停旋转的传送带(Looper)上,系统每取出一个快递,就根据上面标签的内容把它发配到对应的收件人那去,收件人再根据标签上标注的签名(what)来分别处理不同的快递。

 

好了,接下来我讲讲我的心得,说的不对的地方请各位指正。


小误会引发的大问题

在理解Handle-Message机制的过程中,虽然整体的流程和概念我可以很快弄明白,但有个细节一直纠缠着我,如鲠在喉。

就是这个obtainMessage方法。

先来看一下,obtain的英文解释:

       obtain[英][əbˈtein] [美][əbˈtein] 

       vt.获得,得到;流行;买到,达到(目的)

       vi.通行,通用;流行;存在

 

可以见得,这个obtainMessage方法,应该指的是获取相应消息的意思,联系到它的定义:

   public final Message obtainMessage(int what)
    {
       return Message.obtain(this, what);
}

我理所当然的认定这个方法指的是处理事件线程获取目标消息的意思……

因此,之后我的理解统统走了样,通过obtianMessage方法Handler线程得到了对应的消息,那么接下来就应该交给自己handleMessage来处理,可是这个SendMessage方法是什么!谁能告诉我为什么会有 sendMessageDelayed(obtainMessage(EVENT_CALL_RING_CONTINUE,token, 0), mCallRingDelay);这种情况。

把自己辛辛苦苦搜集到的消息再发出去算是怎么回事!?

我彻底混乱了。

 

所以,尽管看了不少的解析消息机制的文章,我还是非常痛苦的理解这个该死的Handle-Message到底是什么意思。

直到读完Message.java代码,我才发现所谓的obtian并不是从“消息源”中获取消息,而是从“消息池”中获取消息啊!所谓的obtianMessage过程,与其理解为获取消息,不如理解为“产生”消息更合适吧。

 

整个的流程应该是这么个顺序才对:

  • 线程A从消息池中挖出一个消息,把自己的戳子,处理对象说明,附加内容等等都加上去,形成一个有实际意义的消息。
  • 通过SendMessage方法,把这个消息加入目标线程的消息队列MessageQueue中去。
  • 这个消息队列由目标线程的Looper维护,Looper会通过loop方法轮询队列中的消息,轮询到这个消息的时候,根据该消息中指向的target目标,调用对应Handler对象的dispatchMessage()方法把它分发给相应的处理方法。虽然通常来说,这个处理方法就是重写后的handleMessage()方法。

这个过程,宏观上看来,就是线程A抛出了一个消息,由自己或者是线程B在适当的时刻进行异步处理,这个处理内容就是handleMessage的回调函数。


把大象塞到冰箱里

原谅我用这个稍显夸张的副标题,不过它确实是我第一次理解Handler类时的真实感想。

为什么叫把大象塞到冰箱里?

原话是这么说的,请问把大象塞到冰箱里要几步?

这个Handler.java给我的感觉就是如此,使用Handler,可以不用纠结到把大象塞到冰箱里究竟应该怎么使劲,只需要知道“开门,塞进去,关门”就ok了。

为什么这么说?

你看我们平时都是怎么做的,上层注册一个消息,然后在对应线程中new一个Handler对象,在Handler对象里重写handleMessage方法处理消息的回调就ok了。细节什么的统统不用管啊……

 

而真实的情况是什么呢,我想有些就如我上小结所写的,有些我还没理解。它应该是线程调度跟消息共享共同作用的结果。而底层封装的太过于漂亮,以至于上面运用它的人只需要开关冰箱门就搞定了消息的回调过程……真是惬意啊。

但是对于androider来说,光会开关冰箱门还是远远不够的,得深入了解才行。对于Handler我仍有很多的疑问,譬如为啥sendMessage()方法中指定的msg.target为this,而不让形参直接传一个进来,这样不是更方便吗?

总之,handler是个非常值得学习的内容,搞定了这个,我才能继续说说真正跟呼叫业务相关的消息触发内容。


1楼lixinnan18昨天 14:35handler 一个线程处理帮助类

    
[2] unity3d中的坑和好决方案
    来源: 互联网  发布时间: 2014-02-18
unity3d中的坑和

unity3d中的坑和

     unity3d是一个很牛x的引擎,当然其也有一些东西是不太好或者说不习惯的,下面列举一些:

1、制作特效时,使用animation记录的位置是相对位置,如果直接放到别的节点下会出问题;

    解决方法:在特效根节点的上一层加上一个transform是(0,0,0) (0,0,0)(1,1,1)的父节点,之后再使用和处理父节点

2、使用NGUI制作界面时,ui特效会有位置对不上的问题(美术不会用ngui,使用原始的模型+材质贴图的形式来做特效)

    解决方法:让美术将特效直接做到ui上面

3、美术制作的特效导出时丢失材质和贴图

:要求美术在建模时不准挂材质,所有的材质不使用自动生成的,而是在unity里面新建、挂接,程序也可以提供删掉默认材质的编辑器扩展插件 (assetImporter as ModelImporter).importMaterials = false;

4、多人间合作时的文件共享和版本控制

:1》Edit->Project Settings->Editor 打开 meta files 2》meta文件和原始文件一起同步 3》checkout时 按住 左边的alt键或option键

5、文本化场景文件

:edit----project setting ----editr 将Asset Serialization 的 mode 设置成Force Text

6、ngui的界面元素无法响应

:制作ui时注意设置摄像机的eventReceiverMask的层为对应的层

7、摄像机看不到ui

:将ui的层设置为摄像机对应的渲染的层

8、脚本中start和update等函数不能继承

:将这几个函数内的逻辑抽象成函数,之后子类中继承这些函数

9、脚本调用时因为空引用而崩溃

:所有初始化工作写在start中,所有功能写到update中,如果仅执行一次,可以加个bool型的开关 10、等待某个特效播完

:可以使用coroutine来等待

11、跨平台动态加载贴图、音频

:使用www

12、周期性的活动,如每4拍换一个舞步

:当前时间/周期 减去整数部分,与0.5比较

13、换装重新组织SkinnedMeshRenderer的sharedMesh时骨骼对不上

:所有avatar的部件的骨架设置要一模一样

14、减少动作文件的大小

:游戏开始时动态的将animation加到mesh上面

15、全局功能需要多处调用

:将全局功能直接挂到程序节点ProgramRoot上,使用时直接 GameObject.Find("ProgramRoot").GetComponentInChildren

16、GameObject.Find找不到隐藏的节点

:定义public GameObject 属性,之后在编辑器里面拖拽

17、各个界面间数据的共享

:创建单独的GameWorld等数据模型模块,并统一实现序列化和反序列化

18、分时的状态逻辑 :coroutine加配置表

19、灵活的object的属性

:Dictionary<string, string> propsTable;

20、灵活的事件响应回调

:统一继承BaseCallBack,里面写具体的逻辑

21、渲染暂停时实现动态效果

:Time.timeScale = 0f; 程序通过 Time.realtimeSinceStartup来手动实现特效效果

22、炫酷的显示得分

:每一位数字用一张数字的贴图来实现

23、ui特效阻碍ui的响应

:调整z值,使特效在ui的后面

24、特殊的运动轨迹和手感 :用animation编辑器做成动画来播放


    
[3] 调用service静态方法抛RuntimeException有关问题
    来源: 互联网  发布时间: 2014-02-18
调用service静态方法抛RuntimeException问题

    假设有一个service类是 AbcSvr在其内有一个static方法供外调用启动自己。

    public static void startAbcSvr(Context ctx ) {
	      ctx.startService(new Intent(ctx, AbcSvr.class));
    }

   在某种情况下回抛出Exception

   Exception Ljava/lang/RuntimeException; thrown while initializing Lcom/XXXX/AbcSvr;
   

    应是Dalvik的一个bug。解决的办法是将startAbcSvr方法移动到其他类去即可。


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3