Handler之消息循环

  1.  

Handler是用于操作线程内部的消息队列的类。这有点绕,没关系,我们慢慢的来讲。前面Looper一篇讲到了Looper是用于给线程创建消息队列用的,也就是说Looper可以让消息队列(MessageQueue)附属在线程之内,并让消息队列循环起来,接收并处理消息。但,我们并不直接的操作消息队列,而是用Handler来操作消息队列,给消息队列发送消息,和从消息队列中取出消息并处理。这就是Handler的职责。
Handler,Looper和MessageQueue是属于一个线程内部的数据,但是它提供给外部线程访问的接口,Handler就是公开给外部线程,与线程通讯的接口。换句话说,这三个东西都是用来线程间通讯用的(ITC--Inter Thread Communication),与进行间通讯(IPC--Inter Process Communication)的消息队列msgque的核心思想是一致的。MessageQueue是相对较底层的,较少直接使用,Looper和Handler就是专门用来操作底层MessageQueue的。
还有一个重要的数据结构是通讯的基本元素,就是消息对象(Message),Message从来不单独使用,它都是跟随Handler来使用的。具体方法可以参考文档,但需要注意的是同一个消息对象不能发送二次,否则会有AndroidRuntimeException: { what=1000 when=-15ms obj=.. } This message is already in use."。每次发送消息前都要通过Message.obtain()来获取新的对象,或者,对于不需要传送额外数据的直接发送空消息就好Handler.sendEmptyMessage(int)。另外也需要注意消息对象是不能手动回收的,也就是说你不能调用Message.recycle()来释放一个消息对象,因为当该对象被从队列中取出处理完毕后,MessageQueue内部会自动的去做recycle()。这个理解起来也很容易,因为发送一个消息到消息队列后,消息什么时候会被处理,对于应用程序来讲是不知道的,只有MessageQueue才会知道,所以只能由MessageQueue来做回收释放的动作。
因为Handler是用于操作一个线程内部的消息队列的,所以Handler必须依附于一个线程,而且只能是一个线程。换句话说,你必须在一个线程内创建Handler,同时指定Handler的回调handlerMessage(Message msg)。
Handler主要有二个用途,一个是用于线程内部消息循环; 另外一个就是用于线程间通讯。
Handler的基本用法可以参考文档,说的还是比较清楚的。

用于线程内部消息循环

主要是用作在将来定时做某个动作,或者循环性,周期性的做某个动作。主要的接口就是

  1. package com.example.handler_simple;
  2.  
  3. import android.media.MediaPlayer;
  4. import android.os.Bundle;
  5. import android.os.Handler;
  6. import android.os.Message;
  7. import android.app.Activity;
  8. import android.util.Log;
  9. import android.view.Menu;
  10. import android.view.SurfaceHolder;
  11. import android.view.SurfaceView;
  12. import android.view.View;
  13. import android.view.View.OnClickListener;
  14. import android.widget.Button;
  15. import android.widget.ProgressBar;
  16.  
  17. public class MainActivity extends Activity {
  18.  
  19. protected static final String TAG = "MainActivity";
  20. private static final int MEDIA_PLAYER_READY = 0;
  21. private static final int REFRESH_PROGRESS = 1;
  22.  
  23. private Button mStart;
  24. private Button mStop;
  25. private Button mPause;
  26. private SurfaceHolder mSurfaceHolder;
  27. private ProgressBar mProgressBar;
  28. private SurfaceView mDisplay;
  29. private MediaPlayer mMediaPlayer;
  30.  
  31. private Handler mMainHandler = new Handler() {
  32. @Override
  33. public void handleMessage(Message msg) {
  34. switch (msg.what) {
  35. case MEDIA_PLAYER_READY:
  36. mProgressBar.setMax(mMediaPlayer.getDuration());
  37. mMediaPlayer
  38. .setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
  39. public void onCompletion(MediaPlayer mp) {
  40. mProgressBar.setProgress(mMediaPlayer
  41. .getDuration());
  42. mMainHandler.removeMessages(REFRESH_PROGRESS);
  43. }
  44. });
  45. mStart.setEnabled(true);
  46. mStop.setEnabled(true);
  47. break;
  48. case REFRESH_PROGRESS:
  49. int cp = mMediaPlayer.getCurrentPosition();
  50. mProgressBar.setProgress(cp);
  51. int delay = 1000 - (cp % 1000);
  52. mMainHandler.sendEmptyMessageDelayed(REFRESH_PROGRESS, delay);
  53. break;
  54. default:
  55. break;
  56. }
  57. }
  58. };
  59.  
  60. protected void onCreate(Bundle savedInstanceState) {
  61. super.onCreate(savedInstanceState);
  62. setContentView(R.layout.activity_main);
  63. initView();
  64. }
  65.  
  66. private void initView() {
  67. // TODO Auto-generated method stub
  68.  
  69. mStart = (Button) this.findViewById(R.id.btn_player);
  70. mPause = (Button) this.findViewById(R.id.btn_pause);
  71. mProgressBar = (ProgressBar) this.findViewById(R.id.progressbar);
  72. mStop = (Button) this.findViewById(R.id.btn_stop);
  73.  
  74. mStart.setOnClickListener(new buttonListenner());
  75. mPause.setOnClickListener(new buttonListenner());
  76. mStop.setOnClickListener(new buttonListenner());
  77. mStop.setEnabled(false);
  78. mDisplay = (SurfaceView) findViewById(R.id.surfaceview);
  79. mSurfaceHolder = mDisplay.getHolder();
  80. mSurfaceHolder.setFixedSize(mDisplay.getWidth(), mDisplay.getHeight());
  81. // Do not believe the document, setType is necessary, otherwise, video
  82. // won't play correctly
  83. // mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  84. // mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_HARDWARE);
  85. new Thread(new Runnable() {
  86. public void run() {
  87. try {
  88. Log.e(TAG, "Thread is runing");
  89. mMediaPlayer = MediaPlayer.create(getApplication(),
  90. R.raw.test);
  91. Log.e(TAG, "Thread is runing");
  92. mMediaPlayer.setDisplay(mSurfaceHolder);
  93. mMainHandler.sendEmptyMessage(MEDIA_PLAYER_READY);
  94. } catch (IllegalArgumentException e) {
  95. Log.e(TAG, "caught exception e", e);
  96. } catch (SecurityException e) {
  97. Log.e(TAG, "caught exception e", e);
  98. } catch (IllegalStateException e) {
  99. Log.e(TAG, "caught exception e", e);
  100. }
  101. }
  102. }).start();
  103. }
  104.  
  105. private class buttonListenner implements OnClickListener {
  106.  
  107. @Override
  108. public void onClick(View v) {
  109.  
  110. switch (v.getId()) {
  111. case R.id.btn_player:
  112. mMediaPlayer.start();
  113. mMainHandler.sendEmptyMessage(REFRESH_PROGRESS);
  114.  
  115. break;
  116. case R.id.btn_pause:
  117. mMainHandler.removeMessages(REFRESH_PROGRESS);
  118. mMediaPlayer.pause();
  119.  
  120. break;
  121. case R.id.btn_stop:
  122.  
  123. break;
  124.  
  125. default:
  126. break;
  127. }
  128.  
  129. }
  130. }
  131.  
  132. @Override
  133. protected void onDestroy() {
  134. super.onDestroy();
  135. mMainHandler.removeMessages(REFRESH_PROGRESS);
  136. if (mMediaPlayer != null) {
  137. mMediaPlayer.release();
  138. }
  139. }
  140.  
  141. public boolean onCreateOptionsMenu(Menu menu) {
  142. // Inflate the menu; this adds items to the action bar if it is present.
  143. getMenuInflater().inflate(R.menu.main, menu);
  144. return true;
  145. }
  146.  
  147. }

:视频播放器与Handler 完美调用的更多相关文章

  1. android开发里跳过的坑——调用已安装视频播放器在有些机器上无效

    调用已安装视频播放器播放未修改之前的代码 private void startPlay(String fileName){ File file = new File(fileName); Intent ...

  2. iOS 调用音乐播放以及视频播放器

    音乐播放 NSString *path = [[NSBundle mainBundle] pathForResource:@"预谋" ofType:@"mp3" ...

  3. Android 音视频深入 十九 使用ijkplayer做个视频播放器(附源码下载)

    项目地址https://github.com/979451341/Myijkplayer 前段时候我觉得FFmpeg做个视频播放器好难,虽然播放上没问题,但暂停还有通过拖动进度条来设置播放进度,这些都 ...

  4. (转)如何基于FFMPEG和SDL写一个少于1000行代码的视频播放器

    原文地址:http://www.dranger.com/ffmpeg/ FFMPEG是一个很好的库,可以用来创建视频应用或者生成特定的工具.FFMPEG几乎为你把所有的繁重工作都做了,比如解码.编码. ...

  5. React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发

    React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发   2016/09/23 |  React Native技术文章 |  Sky丶清|  4 条评论 |  1 ...

  6. Android 视频播放器 (四):使用ExoPlayer播放视频

    一.简介 ExoPlayer是一个Android应用层的媒体播放器,它提供了一套可替换Android MediaPlayer的API,可以播放本地或者是线上的音视频资源.ExoPlayer支持一些An ...

  7. Python应用03 使用PyQT制作视频播放器

    作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁任何形式转载. 最近研究了Python的两个GUI包,Tkinter和PyQT.这两个GUI包的底层分别是Tcl/ ...

  8. 打造自己的html5视频播放器

    前段时间重新学习了一下html5的video部分,以前只是停留在标签的使用上,这一次决定深入了解相关的API,并运用这些API打造一个简单的视频播放器.所谓“打造自己的”,就是要自己重写video标签 ...

  9. 一款开源免费跨浏览器的视频播放器--videojs使用介绍

    最近项目中的视频功能,需要做到浏览器全兼容,所以之前用html5实现的视频功能就需要进行改造了.在网上翻了个遍,试来试去,在所有的视频播放器中,就数它最实际了.首先我们来看看它的优点: 1.它是开源免 ...

随机推荐

  1. nginxhttp请求限制丶tcp会话限制和下载速度限制

    (1)nginx请求限制 ngx_http_limit_req_module:开启对单个ip丶单个会话在单位时间内请求的限制rate表示限制的速率 1.修改nginx配置文件 #vim /usr/lo ...

  2. react native redux saga增加日志功能

    redux-logger地址:https://github.com/evgenyrodionov/redux-logger 目前Reac native项目中已经使用redux功能,异步中间件使用red ...

  3. 架构设计之NodeJS操作消息队列RabbitMQ

    一. 什么是消息队列? 消息(Message)是指在应用间传送的数据.消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象. 消息队列(Message Queue)是一种应用间的通信 ...

  4. Python与SQLite日期时间函数的使法

    SQLite的时间函数跟Python的时间函数有些许差别,所以稍做记录,供自己以后查询. 网上有将SQLite官方WIKI内容翻译成中文的文章,大家有兴趣可以搜索一下,我这里单纯记录一下个人比较常用的 ...

  5. python 正则匹配中文(unicode)(转)

    由于 需求原因,需要匹配 提取中文,大量google下,并没有我需要的.花了一个小时大概测试,此utf8中文通过,特留文.    参考: http://hi.baidu.com/nivrrex/blo ...

  6. ZOJ 3495 Lego Bricks

    计算几何,暴力. 题目中有一句话:$The$ $mass$ $of$ $each$ $brick$ $is$ $equally$ $distributed$ $and$ $it$ $will$ $be ...

  7. 洛谷P3805 [模板]Manacher算法 [manacher]

    题目传送门 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入输出格式 输入格式: 一行小写英文字符a,b,c...y,z组成的字符 ...

  8. TensorFlow-GPU安装配置(win10+tensorflow1.6+CUDA9.0+cudnn7.0+python3.6+Visual Studio2013)

    安装步骤: TensorFlow官网 tensorflow一般只能装在python3上,CUDA9.0搭配cudnn7.0,CUDA8.0搭配cudnn6.0 查看对应要安装的环境版本(因为会不断更新 ...

  9. Linux命令之firewall-cmd

    firewall-cmd [选项] firewall-cmd是firewalld守护程序的命令行客户端.它提供了管理运行时和永久配置的接口.firewalld中的运行时配置与永久配置分开.这意味着可以 ...

  10. 现代CSS清除浮动

    清除浮动 排除远古时代的hack解决方案,比如那些要兼容IE6~8的方法.其实总结起来,大致有三种方法: overflow 原理解析:块级格式上下文规定了页面必须自动包含突出的浮动元素! 而overf ...