仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 507|回复: 9
打印 上一主题 下一主题

[学习教程] JAVA网页设计我了解的Hanlder--android动静传送机制仓酷云

[复制链接]
莫相离 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:15:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
对于一个大型项目,如果用java来作,可能需要9个月,并且可能需要翻阅10本以上的书,但如果用ruby来作,3个月,3本书就足够了,而.net网页编程也不过3,4本书足以,这就是区别。每个进修Android的同砚城市以为Handler是一个奇妙的工具,我也一样,入手下手我觉得我懂了Handler的机制,厥后发明本人是一孔之见,今天想一想,我可否本人完成一个Handler,让子线程与ActivityUI线程通讯,假如可以本人完成一个Handler,那一定是对Handler的动静传送机制了解浸透了。
1、引进
  Android的UI是单线程把持的,实践上,乐成的UI框架都是基于单线程的,多线程的UI框架常常由于办理并发和逝世锁的困难而胎逝世腹中。只要UI线程能把持界面控件,但我们老是但愿子线程的数据能更新到UI上,因而就有了Handler,它匡助我们完成了非UI线程向UI线程之间的通讯,Handler的利用十分复杂。
  一个复杂的示例,让一个TextView静态显现秒数:  
  1. 1publicclassMainActivityextendsActivity{2privatestaticfinalintUPDATE_TAG=0x01;3privateTextViewtextView;45@Override6protectedvoidonCreate(BundlesavedInstanceState){7super.onCreate(savedInstanceState);8setContentView(R.layout.activity_main);9textView=(TextView)findViewById(R.id.textview);10//启动一个线程11newThread(newRunnable(){1213@Override14publicvoidrun(){15intcount=1;16while(true){17//发送计数值到handler18mHandler.obtainMessage(UPDATE_TAG,String.valueOf(count))19.sendToTarget();20try{21TimeUnit.SECONDS.sleep(1);22}catch(InterruptedExceptione){23e.printStackTrace();24}25}26}2728}).start();29}3031publicHandlermHandler=newHandler(){32publicvoidhandleMessage(Messagemsg){33switch(msg.what){34caseUPDATE_TAG:35//显现计数值36textView.setText((String)msg.obj);37break;38}39}40};41}
复制代码

  经由过程开启一个线程,线程每隔一秒发送一次计数给handler,让handler来更新TextView的内容,新开的子线程内里不克不及间接操控TextView,由于这违背了UI线程了单线程把持标准,假如你真要这么做,一运转就会失掉CalledFromWrongThreadException非常。
2、这不就是一个察看着形式么?
  最后本人了解的Handler就是一个典范的察看着形式。sendToTarget()这个办法必定以某种体例挪用了Handler的handleMessage(Messagemsg)办法,从而完成了我们指定的义务,因而我写了上面如许一个Handler和Message
  1. /****摹拟Android的Handler,声名一个供子类掩盖的办法和多个天生动静的办法*/publicclassHandler{/****子类掩盖本办法,完成想要的操纵**@parammsg*/protectedvoidhandleMessage(Messagemsg){}publicMessageobtainMessage(intwhat){Messagemsg=newMessage(this,what,-1,-1,null);returnmsg;}publicMessageobtainMessage(intwhat,Objectobj){Messagemsg=newMessage(this,what,-1,-1,obj);returnmsg;}publicMessageobtainMessage(intwhat,intarg1,intarg2,Objectobj){Messagemsg=newMessage(this,what,arg1,arg2,obj);returnmsg;}}
复制代码

  上去就是Message类:  
  1. /****摹拟Android的Message,这里为便利演示,只写了一个机关办法。机关办法中绑定了一个Handler*/publicclassMessage{privatefinalHandlertarget;publicfinalintwhat;publicfinalintarg1;publicfinalintarg2;publicfinalObjectobj;publicMessage(Handlertarget,intwhat,intarg1,intarg2,Objectobj){this.target=target;this.arg1=arg1;this.arg2=arg2;this.what=what;this.obj=obj;}/****使用OOP的多态,挪用子类的掩盖办法*/publicvoidsendToTarget(){target.handleMessage(this);}}
复制代码

  测试代码以下:  
ViewCode
  真想说下面的代码表现了一个复杂的察看着形式,下面的测试代码能运转。可是,可是如许的Handler能取代Android的Handler在Activity中利用吗,用下面的Handler往替换Android的handler,了局失掉是CalledFromWrongThreadException。
  这很明显的,下面的Handler能够只仿照到AndroidHandler的形,没有仿照到其神,它只是经由过程一个回调仿照了Handler的事情表面,使用多态的手段往挪用子类的handleMessage办法,设法是好的,但这终极相称于让子线程间接挪用了handleMessage,从而让子线程对界面控件举行了操控,违反了UI界面的单线程把持准绳,必需会报CalledFromWrongThreadException的非常。
3、子线程是怎样把动静传送给UI线程
  后面仿制的Handler让子线程经由过程Message利用了UI控件,因而会报错,那Android是怎样将子历程的动静发送给UI历程。实践上Handler的事情离不开以下几个组件:


  • Message:Handler吸收和处置的对象
  • MessageQueue:动静行列,以FIFO的体例办理Message对象
  • Looper:办理MessageQueue的对象,不休地从MessageQueue中作废息,并发送该动静对应的Handler举行处置。每一个线程只要一个Looper,UI线程在创立时就已默许创立了一个Looper,因而在Activity中能够间接创立Handler便可发送和处置动静;假如在子线程中创立Handler,必需在创立前挪用Looper.prepare();如许Looper在才干做好筹办,并为以后线程创立MessageQueue,以便承受Handler的Message。能够看一下Looper.prepare()的源码
    1. publicstaticvoidprepare(){prepare(true);}privatestaticvoidprepare(booleanquitAllowed){if(sThreadLocal.get()!=null){thrownewRuntimeException("OnlyoneLoopermaybecreatedperthread");}sThreadLocal.set(newLooper(quitAllowed));}privateLooper(booleanquitAllowed){//公有的机关办法mQueue=newMessageQueue(quitAllowed);mRun=true;mThread=Thread.currentThread();}
    复制代码

    在子历程创立好Handler后,挪用Looper.loop()处置动静。Looper.loop()是一个逝世轮回,假如不实行quit(),厥后的代码将不会实行。如今看一个例子,我们经由过程点击Button给子线程的Hanlder传送动静。
    1. publicclassMainActivityextendsActivity{privateMythreadthread;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);thread=newMythread();thread.start();  }classMythreadextendsThread{publicHandlerhandler;@Overridepublicvoidrun(){Looper.prepare();//在子线程中界说Handlerhandler=newHandler(){publicvoidhandleMessage(Messagemsg){Log.i("handleMessage","子线程handler.handleMessage(...)");//接到动静让Looper加入逝世轮回handler.getLooper().quit();}};Toast.makeText(MainActivity.this,"beforeLooper.loop()",Toast.LENGTH_LONG).show();//逝世轮回处置动静Looper.loop();Toast.makeText(MainActivity.this,"afterLooper.loop()",Toast.LENGTH_LONG).show();}};publicvoidonClickButton(Viewv){thread.handler.obtainMessage().sendToTarget();}}
    复制代码


  能够看到线程启动后,会Toast"beforeLooper.loop()",但不会立即Toast"afterLooper.loop()",只要当我们按下Button后才会显现"afterLooper.loop()",由于按下Button,会给子线程的Handler发送一个空动静,而我们界说Handler抵消息的处置是挪用looper的quit(),从而停止Looper.loop()。注重quit()并非复杂的停止Looper.loop(),而是设置MessageQueue的一个标记,让MessageQueue的next()办法前往null,从而停止Looper.loop(),概况请看MessageQueue源码,这里我们来看看loop()的源码:


    1. publicstaticvoidloop(){...for(;;){Messagemsg=queue.next();//mightblockif(msg==null){//Nomessageindicatesthatthemessagequeueisquitting.return;}...msg.target.dispatchMessage(msg);...msg.recycle();}}
    复制代码


  别的跟踪sendToTarget()发明终极挪用的办法是MessageQueue的enqueueMessage(Messagemsg,longwhen),这个办法只是把message放进行列中,并没有挪用动静动静办法,动静的分发处置是在Looper的loop()中举行的。
4、是甚么工具再帮UI线程跑Looper.loop()
  如今理清了后面的成绩又来了新的成绩,是谁在帮UI线程跑Looper.loop():


  • 假如是其他线程帮它Looper.loop(),那末这分明违反了UI线程的单线程把持标准;
  • 假如是UI线程本人在跑,那它的逝世轮回在那边跑着,怎样用光阴往实行onCreate(),onResume()...和我们绑定的各类listener。
  假如既要满意UI线程的单线程把持标准,又要让逝世轮回Looper.loop()跑着不遗漏一个动静,还要呼应onCreate()、listener,只要一种举措,那就是对界面的一切的操纵都是由loop来驱动分发的,onCreate(),onResume()...各类listener都是Looper.loop()来挪用。
  实践上Android就是这么干的,要理清onCreate等各类办法绑定的Message的历程不简单,可是我们能够很复杂地考证我们的下面的假定,那就是在onCreate(),onResume(),和listener的呼应办法内里激发非常,然后看一下栈信息,我们在onCreate发放中加一句inta=1/0,看看非常的栈信息:
  当发明奇妙的Handler本来就是靠一个逝世轮回来保持的,统统就变得名顿开了。

Java到底会发战成什么样,让我们拭目以待吧,我始终坚信着java会更好。以上都是俺个人看法,欢迎大家一起交流.
第二个灵魂 该用户已被删除
沙发
发表于 2015-1-20 18:52:10 | 只看该作者
你可以去承接一些项目做了,一开始可能有些困难,可是你有技术积累,又考虑周全,接下项目来可以迅速作完,相信大家以后都会来找你的,所以Money就哗啦啦的。。。。。。
不帅 该用户已被删除
板凳
发表于 2015-1-29 14:59:39 | 只看该作者
Sun公司看见Oak在互联网上应用的前景,于是改造了Oak,于1995年5月以Java的名称正式发布。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。
爱飞 该用户已被删除
地板
发表于 2015-2-5 15:41:25 | 只看该作者
吧,现在很流行的Structs就是它的一种实现方式,不过Structs用起来实在是很繁,我们只要学习其精髓即可,我们完全可以设计自己的MVC结构。然后你再研究一下软件Refactoring (重构)和极限XP编程,相信你又会上一个台阶。 做完这些,你不如整理一下你的Java代码,把那些经典的程序和常见的应用整理出来,再精心打造一番,提高其重用性和可扩展性。你再找几个志同道合的朋友成立一个工作室吧
莫相离 该用户已被删除
5#
 楼主| 发表于 2015-2-12 19:40:53 | 只看该作者
接着就是EJB了,EJB就是Enterprise JavaBean, 看名字好象它是Javabean,可是它和Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的 Weblogic,Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。
老尸 该用户已被删除
6#
发表于 2015-2-12 19:49:04 | 只看该作者
应用在电视机、电话、闹钟、烤面包机等家用电器的控制和通信。由于这些智能化家电的市场需求没有预期的高,Sun公司放弃了该项计划。随着1990年代互联网的发展
冷月葬花魂 该用户已被删除
7#
发表于 2015-3-3 04:45:04 | 只看该作者
有时间再研究一下MVC结构(把Model-View-Control分离开的设计思想)
飘灵儿 该用户已被删除
8#
发表于 2015-3-11 05:33:13 | 只看该作者
不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。
兰色精灵 该用户已被删除
9#
发表于 2015-3-19 11:56:03 | 只看该作者
吧,现在很流行的Structs就是它的一种实现方式,不过Structs用起来实在是很繁,我们只要学习其精髓即可,我们完全可以设计自己的MVC结构。然后你再研究一下软件Refactoring (重构)和极限XP编程,相信你又会上一个台阶。 做完这些,你不如整理一下你的Java代码,把那些经典的程序和常见的应用整理出来,再精心打造一番,提高其重用性和可扩展性。你再找几个志同道合的朋友成立一个工作室吧
深爱那片海 该用户已被删除
10#
发表于 2015-3-27 21:12:36 | 只看该作者
是一种由美国SUN计算机公司(Sun Microsystems, Inc.)所研究而成的语言
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-23 21:41

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表