- 浏览: 54205 次
- 性别:
- 来自: 北京
博客专栏
-
设计模式
浏览量:7123
文章分类
最新评论
-
alixjiang:
getInstance应该在同步锁的保护之下吧
设计模式-单例模式 -
再_见孙悟空:
就是信息的转发
设计模式-中介者模式 -
DanielHan:
中介者模式中,中介者参与同事角色之间的通信方式,使用的是观察者 ...
设计模式-中介者模式 -
net_hare:
这个和观察者模式有什么区别
设计模式-中介者模式 -
xinglan500:
用代码解释很好哦。多谢博主啦。
JAVA反射机制之一
Android中有着和J2SE同样优秀的多线程支持,可以把那些耗时较多的操作放在新线程中操作。但是当新线程中有涉及到操作UI的操作时,就会对主线程产生危险,因此,Android提供了Handler作为主线程和子线程的纽带。同时,Handler对象初始化后,就默认与对它初始化的进程的消息队列绑定,因此可以利用Handler所包含的消息队列,制定一些操作的顺序。
下面,就Handler的以上两点作用,分别进行讨论。
1. 传递Message。用于接受子线程发送的数据, 并用此数据配合主线程更新UI。
在Android中,对于UI的操作通常需要放在主线程中进行操作。如果在子线程中有关于UI的操作,那么就需要把数据消息作为一个Message对象发送到消息队列中,然后,有Handler中的handlerMessge方法处理传过来的数据信息,并操作UI。当然,Handler对象是在主线程中初始化的,以为它需要绑定在主线程的消息队列中。
类sendMessage(Message msg)方法实现发送消息的操作。 在初始化Handler对象时重写的handleMessage方法来接收Messgae并进行相关操作。
以上的例子中,子线程只是对进度条的参数进行了变更,并将结果以message形式发送到消息队列中去,子线程的内部并未进行UI操作,而是在重写的Handler的handlerMessage方法中操作了UI界面。
2. 传递Runnable对象。用于通过Handler绑定的消息队列,安排不同操作的执行顺序。
Handler对象在进行初始化的时候,会默认的自动绑定消息队列。利用类post方法,可以将Runnable对象发送到消息队列中,按照队列的机制按顺序执行不同的Runnable对象中的run方法。
程序的运行结果就是每隔3秒钟,就会在控制台打印一行UpdateTread。这是因为实现了Runnable接口的updateThread对象进入了空的消息队列即被立即执行run方法,而在run方法的内部,又在3000ms之后将其再次发送进入消息队列中。
3. Handler和多线程
post方法虽然发送的是一个实现了Runnable接口的类对象,但是它并非创建了一个新线程,而是执行了该对象中的run方法。也就是说,整个run中的操作和主线程处于同一个线程。
这样对于那些简单的操作,似乎并不会影响。但是对于耗时较长的操作,当它被加入到消息队列中之后执行会占用很长的时间,以至于处于同一线程的其他操作无法继续执行,就会出现“假死”。为了解决这个问题,就需要使得handler绑定到一个新开启线程的消息队列上,在这个处于另外线程的上的消息队列中处理传过来的Runnable对象和消息。
这样,当使用sendMessage方法传递消息或者使用post方法传递Runnable对象时,就会把它们传递到与handler对象绑定的处于另外一个线程的消息队列中,它们将在另外的消息队列中被处理。而主线程还会在发送操作完成时候继续进行,不会影响当前的操作。
这里需要注意,这里用到的多线程并非由Runnable对象开启的,而是ThreadHandler对象开启的。Runnable对象只是作为一个封装了操作的对象被传递,并未产生新线程
下面,就Handler的以上两点作用,分别进行讨论。
1. 传递Message。用于接受子线程发送的数据, 并用此数据配合主线程更新UI。
在Android中,对于UI的操作通常需要放在主线程中进行操作。如果在子线程中有关于UI的操作,那么就需要把数据消息作为一个Message对象发送到消息队列中,然后,有Handler中的handlerMessge方法处理传过来的数据信息,并操作UI。当然,Handler对象是在主线程中初始化的,以为它需要绑定在主线程的消息队列中。
类sendMessage(Message msg)方法实现发送消息的操作。 在初始化Handler对象时重写的handleMessage方法来接收Messgae并进行相关操作。
//Handler处理子线程消息代码示例: public class Activity01 extends Activity { //声明ProgressBar对象 private ProgressBar m_ProgressBar; private ProgressBar m_ProgressBar2; private Button mButton01; protected static final int GUI_STOP_NOTIFIER = 0x108; protected static final int GUI_THREADING_NOTIFIER = 0x109; public int intCounter=0; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //设置窗口模式,,因为需要显示进度条在标题栏 requestWindowFeature(Window.FEATURE_PROGRESS); setProgressBarVisibility(true); setContentView(R.layout.main); //取得ProgressBar m_ProgressBar = (ProgressBar) findViewById(R.id.ProgressBar01); m_ProgressBar2= (ProgressBar) findViewById(R.id.ProgressBar02); mButton01 = (Button)findViewById(R.id.Button01); m_ProgressBar.setIndeterminate(false); m_ProgressBar2.setIndeterminate(false); //当按钮按下时开始执行, mButton01.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub //设置ProgressBar为可见状态 m_ProgressBar.setVisibility(View.VISIBLE); m_ProgressBar2.setVisibility(View.VISIBLE); //设置ProgressBar的最大值 m_ProgressBar.setMax(100); //设置ProgressBar当前值 m_ProgressBar.setProgress(0); m_ProgressBar2.setProgress(0); //通过线程来改变ProgressBar的值 new Thread(new Runnable() { public void run() { for (int i = 0; i < 10; i++) { try { intCounter = (i + 1) * 20; Thread.sleep(1000); if (i == 4) { Message m = new Message(); m.what = Activity01.GUI_STOP_NOTIFIER; Activity01.this.myMessageHandler.sendMessage(m); //将message发送到消息队列 break; } else { Message m = new Message(); m.what = Activity01.GUI_THREADING_NOTIFIER; Activity01.this.myMessageHandler.sendMessage(m); //将message发送到消息队列 } } catch (Exception e) { e.printStackTrace(); } } } }).start(); } }); } //通过匿名类复写Handler类中的handleMessage方法,用于接收传递到消息队列中的Message,并进行UI操作。 Handler myMessageHandler = new Handler() { // @Override public void handleMessage(Message msg) { switch (msg.what) { //ProgressBar已经是对大值 case Activity01.GUI_STOP_NOTIFIER: m_ProgressBar.setVisibility(View.GONE); m_ProgressBar2.setVisibility(View.GONE); Thread.currentThread().interrupt(); break; case Activity01.GUI_THREADING_NOTIFIER: if (!Thread.currentThread().isInterrupted()) { // 改变ProgressBar的当前值 m_ProgressBar.setProgress(intCounter); m_ProgressBar2.setProgress(intCounter); // 设置标题栏中前景的一个进度条进度值 setProgress(intCounter*100); // 设置标题栏中后面的一个进度条进度值 setSecondaryProgress(intCounter*100);// } break; } super.handleMessage(msg); } }; }
以上的例子中,子线程只是对进度条的参数进行了变更,并将结果以message形式发送到消息队列中去,子线程的内部并未进行UI操作,而是在重写的Handler的handlerMessage方法中操作了UI界面。
2. 传递Runnable对象。用于通过Handler绑定的消息队列,安排不同操作的执行顺序。
Handler对象在进行初始化的时候,会默认的自动绑定消息队列。利用类post方法,可以将Runnable对象发送到消息队列中,按照队列的机制按顺序执行不同的Runnable对象中的run方法。
public class HandlerActivity extends Activity { /** Called when the activity is first created. */ //声明两个按钮控件 private Button startButton = null; private Button endButton = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //根据控件的ID得到代表控件的对象,并未这两个按钮设置相应的监听器 startButton = (Button)findViewById(R.id.startButton); startButton.setOnClickListener(new StartButtonListener()); endButton = (Button)findViewById(R.id.endButton); endButton.setOnClickListener(new EndButtonListener()); } class StartButtonListener implements OnClickListener{ @Override public void onClick(View v) { //调用Handler的post方法,将要执行的线程对象添加到队列当中 handler.post(updateThread); } } class EndButtonListener implements OnClickListener{ @Override public void onClick(View v) { handler.removeCallbacks(updateThread); } } //创建一个Handler对象 Handler handler = new Handler(); //将要执行的操作写在线程对象的run方法当中 Runnable updateThread = new Runnable(){ @Override public void run() { System.out.println("UpdateThread"); //在run方法内部,执行postDelayed或者是post方法 handler.postDelayed(updateThread, 3000); } }; }
程序的运行结果就是每隔3秒钟,就会在控制台打印一行UpdateTread。这是因为实现了Runnable接口的updateThread对象进入了空的消息队列即被立即执行run方法,而在run方法的内部,又在3000ms之后将其再次发送进入消息队列中。
3. Handler和多线程
post方法虽然发送的是一个实现了Runnable接口的类对象,但是它并非创建了一个新线程,而是执行了该对象中的run方法。也就是说,整个run中的操作和主线程处于同一个线程。
这样对于那些简单的操作,似乎并不会影响。但是对于耗时较长的操作,当它被加入到消息队列中之后执行会占用很长的时间,以至于处于同一线程的其他操作无法继续执行,就会出现“假死”。为了解决这个问题,就需要使得handler绑定到一个新开启线程的消息队列上,在这个处于另外线程的上的消息队列中处理传过来的Runnable对象和消息。
public class HandlerTest2 extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main); //打印了当前线程的ID System.out.println("Activity-->" + Thread.currentThread().getId()); //生成一个HandlerThread对象 HandlerThread handlerThread = new HandlerThread("handler_thread"); //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start(),同时开启一个新线程; handlerThread.start(); //将由HandlerThread获取的Looper传递给Handler对象,即由处于另外线程的Looper代替handler初始化时默认绑定的消息队列来处理消息。 MyHandler myHandler = new MyHandler(handlerThread.getLooper()); Message msg = myHandler.obtainMessage(); //将msg发送到目标对象,所谓的目标对象,就是生成该msg对象的handler对象 Bundle b = new Bundle(); b.putInt("age", 20); b.putString("name", "Jhon"); msg.setData(b); msg.sendToTarget(); //将msg发送到myHandler } //定义类 class MyHandler extends Handler{ public MyHandler(){ } public MyHandler(Looper looper){ super(looper); } @Override public void handleMessage(Message msg) { Bundle b = msg.getData(); int age = b.getInt("age"); String name = b.getString("name"); System.out.println("age is " + age + ", name is" + name); System.out.println("Handler--->" + Thread.currentThread().getId()); System.out.println("handlerMessage"); } } }
这样,当使用sendMessage方法传递消息或者使用post方法传递Runnable对象时,就会把它们传递到与handler对象绑定的处于另外一个线程的消息队列中,它们将在另外的消息队列中被处理。而主线程还会在发送操作完成时候继续进行,不会影响当前的操作。
这里需要注意,这里用到的多线程并非由Runnable对象开启的,而是ThreadHandler对象开启的。Runnable对象只是作为一个封装了操作的对象被传递,并未产生新线程
发表评论
-
Android中path的arcTo方法的使用
2014-09-26 16:28 1158该方法的声明为: void Android.graphics ... -
drawable不同目录你会怎么选择(Android)
2014-09-26 15:18 629可以接触Android的会有一个疑问,为什么res下面会有这么 ... -
android调用手机联系人
2014-09-24 14:11 0一.选择联系人 startActivityForResul ... -
Android中全屏无标题设置
2014-09-24 13:06 546方法一:在java代码中实现 this.requestWi ... -
tools:context的作用
2014-08-05 13:32 578tools:context="activity na ... -
Android平台调用WebService详解
2014-08-05 10:32 497http://blog.csdn.net/lyq8479/ar ... -
Android开发之WebService介绍
2014-08-05 10:31 548http://blog.csdn.net/lyq8479/ar ... -
java中的匿名内部类总结
2014-07-16 14:45 406匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部 ... -
两分钟彻底让你明白Android Activity生命周期(图文)!
2014-07-16 09:39 560大家好,今天给大家详解一下Android中Activity的生 ... -
StateListDrawable资源
2014-07-15 21:18 1270StateListDrawable用于组织多个Draw ... -
Android home键和back键区别
2014-07-15 13:04 782back键 Android的程序无需刻意的去退出,当你一按下手 ... -
ImageView的ScaleType属性
2014-07-15 12:54 971图片说明Andorid中ImageView的不同属性Scale ... -
存储方式三:数据库SQLite(SQLiteOpenHelper)
2014-07-09 18:23 556SQLHelper.java package com.ex ... -
存储方式二:文件(XML XmlPull解析)
2014-07-09 13:30 5121.读 LinkMan.java package com. ... -
存储方式二:文件(XML SAX解析)
2014-07-08 19:40 374LinkMan.java package com.exam ... -
存储方式二:文件(XML DOM解析)
2014-07-08 19:41 4091.写 package com.example.filed ... -
存储方式二:文件(raw下的文本文件)
2014-07-08 13:47 682package com.example.filedemo; ... -
存储方式二:文件(文本文件)
2014-07-08 13:37 522一.写 FileOutputStream output ... -
存储方式一:SharedPreferences
2014-07-08 10:08 362一.添加数据 SharedPreferences shar ... -
四大组件-ContentProvider
2014-07-07 22:25 0一.简介 ContentProvider即内容提供器, ...
相关推荐
赠送jar包:netty-handler-4.1.73.Final.jar; 赠送原API文档:netty-handler-4.1.73.Final-javadoc.jar; 赠送源代码:netty-handler-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-handler-4.1.73....
handler发送和接收message的各种方式 (1)Handler.SendEmptyMessage(what); (2)Handler.obtainMessage(int what, int arg1, int arg2, Object obj).sendYToTarget(); (3)Message.obtain(handler, MESSAGE_MSG, 0, 0, ...
* 创建一个Handler对象,使用Handler对象h把Runnable的对象r压入队列 * 此时只会会执行Run()方法,但是不会开启新的线程 */ //Handler h = new Handler(); //h.post(r); /* * 在java中真正开启...
demo01: 通过handler.post()的方法可以更新ui demo02: 一秒钟切换一张图片 demo03: 霓虹灯动态效果的显示 demo04: 倒计时,停止倒计时 demo05: 通过handler.sendMessage和handleMessage发送处理消息 demo06: message...
赠送jar包:netty-handler-4.1.68.Final.jar; 赠送原API文档:netty-handler-4.1.68.Final-javadoc.jar; 赠送源代码:netty-handler-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-handler-4.1.68....
通过 Foxit PDF Preview Handler 可以让你的OutLook2007预览PDF 文件。 Foxit PDF Preview Handler 1.1 For XP
赠送jar包:netty-handler-4.1.24.Final.jar; 赠送原API文档:netty-handler-4.1.24.Final-javadoc.jar; 赠送源代码:netty-handler-4.1.24.Final-sources.jar; 赠送Maven依赖信息文件:netty-handler-4.1.24....
android 中Handler 的几种写法,很简单的demo,大神简单修改下,用的是Handler.Callback,的方法
赠送jar包:netty-handler-4.1.65.Final.jar; 赠送原API文档:netty-handler-4.1.65.Final-javadoc.jar; 赠送源代码:netty-handler-4.1.65.Final-sources.jar; 赠送Maven依赖信息文件:netty-handler-4.1.65....
Handler对象中使用匿名内部类或非静态内部类正确地释放消息避免内存泄漏或增加Native内存,在Android中,Handler对象通常会被用来在主线程(UI线程)中处理消息,以更新UI界面。当我们在Handler对象中使用匿名内部类...
资源包括如何在一个activity A里激活另一个activity B。 然后在两个activity之间用handler传输数据。在activity A里定义全局变量handler,用sendMessage来发数据,在handler里数据以消息队列的方式发送。
赠送jar包:netty-handler-proxy-4.1.68.Final.jar; 赠送原API文档:netty-handler-proxy-4.1.68.Final-javadoc.jar; 赠送源代码:netty-handler-proxy-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-...
赠送jar包:netty-handler-4.1.74.Final.jar; 赠送原API文档:netty-handler-4.1.74.Final-javadoc.jar; 赠送源代码:netty-handler-4.1.74.Final-sources.jar; 赠送Maven依赖信息文件:netty-handler-4.1.74....
赠送jar包:netty-handler-proxy-4.1.73.Final.jar; 赠送原API文档:netty-handler-proxy-4.1.73.Final-javadoc.jar; 赠送源代码:netty-handler-proxy-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-...
赠送jar包:netty-handler-proxy-4.1.73.Final.jar; 赠送原API文档:netty-handler-proxy-4.1.73.Final-javadoc.jar; 赠送源代码:netty-handler-proxy-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-...
感谢慕课网,浅谈handler
赠送jar包:netty-handler-4.1.65.Final.jar; 赠送原API文档:netty-handler-4.1.65.Final-javadoc.jar; 赠送源代码:netty-handler-4.1.65.Final-sources.jar; 赠送Maven依赖信息文件:netty-handler-4.1.65....
Handler使用简单功能强大,常被用作线程间传递消息的组件,而且还可以用于跨进程。 消息机制背后有包括Looper ,MessageQueue管理和分发消息的实现,同时在Native层也单独实现了一套类 似的机制,接收和处理Native...
Handler与AsyncTask使用示例,Handler AsyncTask 示例 looper
js访问handler中任意方法; 访问一般处理程序;