:视频播放器与Handler 完美调用
Handler之消息循环
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的基本用法可以参考文档,说的还是比较清楚的。
用于线程内部消息循环
主要是用作在将来定时做某个动作,或者循环性,周期性的做某个动作。主要的接口就是
package com.example.handler_simple; import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar; public class MainActivity extends Activity { protected static final String TAG = "MainActivity";
private static final int MEDIA_PLAYER_READY = 0;
private static final int REFRESH_PROGRESS = 1; private Button mStart;
private Button mStop;
private Button mPause;
private SurfaceHolder mSurfaceHolder;
private ProgressBar mProgressBar;
private SurfaceView mDisplay;
private MediaPlayer mMediaPlayer; private Handler mMainHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MEDIA_PLAYER_READY:
mProgressBar.setMax(mMediaPlayer.getDuration());
mMediaPlayer
.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mProgressBar.setProgress(mMediaPlayer
.getDuration());
mMainHandler.removeMessages(REFRESH_PROGRESS);
}
});
mStart.setEnabled(true);
mStop.setEnabled(true);
break;
case REFRESH_PROGRESS:
int cp = mMediaPlayer.getCurrentPosition();
mProgressBar.setProgress(cp);
int delay = 1000 - (cp % 1000);
mMainHandler.sendEmptyMessageDelayed(REFRESH_PROGRESS, delay);
break;
default:
break;
}
}
}; protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
} private void initView() {
// TODO Auto-generated method stub mStart = (Button) this.findViewById(R.id.btn_player);
mPause = (Button) this.findViewById(R.id.btn_pause);
mProgressBar = (ProgressBar) this.findViewById(R.id.progressbar);
mStop = (Button) this.findViewById(R.id.btn_stop); mStart.setOnClickListener(new buttonListenner());
mPause.setOnClickListener(new buttonListenner());
mStop.setOnClickListener(new buttonListenner());
mStop.setEnabled(false);
mDisplay = (SurfaceView) findViewById(R.id.surfaceview);
mSurfaceHolder = mDisplay.getHolder();
mSurfaceHolder.setFixedSize(mDisplay.getWidth(), mDisplay.getHeight());
// Do not believe the document, setType is necessary, otherwise, video
// won't play correctly
// mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_HARDWARE);
new Thread(new Runnable() {
public void run() {
try {
Log.e(TAG, "Thread is runing");
mMediaPlayer = MediaPlayer.create(getApplication(),
R.raw.test);
Log.e(TAG, "Thread is runing");
mMediaPlayer.setDisplay(mSurfaceHolder);
mMainHandler.sendEmptyMessage(MEDIA_PLAYER_READY);
} catch (IllegalArgumentException e) {
Log.e(TAG, "caught exception e", e);
} catch (SecurityException e) {
Log.e(TAG, "caught exception e", e);
} catch (IllegalStateException e) {
Log.e(TAG, "caught exception e", e);
}
}
}).start();
} private class buttonListenner implements OnClickListener { @Override
public void onClick(View v) { switch (v.getId()) {
case R.id.btn_player:
mMediaPlayer.start();
mMainHandler.sendEmptyMessage(REFRESH_PROGRESS); break;
case R.id.btn_pause:
mMainHandler.removeMessages(REFRESH_PROGRESS);
mMediaPlayer.pause(); break;
case R.id.btn_stop: break; default:
break;
} }
} @Override
protected void onDestroy() {
super.onDestroy();
mMainHandler.removeMessages(REFRESH_PROGRESS);
if (mMediaPlayer != null) {
mMediaPlayer.release();
}
} public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} }
:视频播放器与Handler 完美调用的更多相关文章
- android开发里跳过的坑——调用已安装视频播放器在有些机器上无效
调用已安装视频播放器播放未修改之前的代码 private void startPlay(String fileName){ File file = new File(fileName); Intent ...
- iOS 调用音乐播放以及视频播放器
音乐播放 NSString *path = [[NSBundle mainBundle] pathForResource:@"预谋" ofType:@"mp3" ...
- Android 音视频深入 十九 使用ijkplayer做个视频播放器(附源码下载)
项目地址https://github.com/979451341/Myijkplayer 前段时候我觉得FFmpeg做个视频播放器好难,虽然播放上没问题,但暂停还有通过拖动进度条来设置播放进度,这些都 ...
- (转)如何基于FFMPEG和SDL写一个少于1000行代码的视频播放器
原文地址:http://www.dranger.com/ffmpeg/ FFMPEG是一个很好的库,可以用来创建视频应用或者生成特定的工具.FFMPEG几乎为你把所有的繁重工作都做了,比如解码.编码. ...
- React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发
React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发 2016/09/23 | React Native技术文章 | Sky丶清| 4 条评论 | 1 ...
- Android 视频播放器 (四):使用ExoPlayer播放视频
一.简介 ExoPlayer是一个Android应用层的媒体播放器,它提供了一套可替换Android MediaPlayer的API,可以播放本地或者是线上的音视频资源.ExoPlayer支持一些An ...
- Python应用03 使用PyQT制作视频播放器
作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁任何形式转载. 最近研究了Python的两个GUI包,Tkinter和PyQT.这两个GUI包的底层分别是Tcl/ ...
- 打造自己的html5视频播放器
前段时间重新学习了一下html5的video部分,以前只是停留在标签的使用上,这一次决定深入了解相关的API,并运用这些API打造一个简单的视频播放器.所谓“打造自己的”,就是要自己重写video标签 ...
- 一款开源免费跨浏览器的视频播放器--videojs使用介绍
最近项目中的视频功能,需要做到浏览器全兼容,所以之前用html5实现的视频功能就需要进行改造了.在网上翻了个遍,试来试去,在所有的视频播放器中,就数它最实际了.首先我们来看看它的优点: 1.它是开源免 ...
随机推荐
- AC日记——餐巾计划问题 洛谷 P1084
餐巾计划问题 思路: 氧气优化水过: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 4005 #define ...
- sql几种删除语句的联系与区别
DELETE.TRUNCATE.DROP三种删除语句联系与区别 相同点: 1.truncate和不带where子句的delete.以及drop都会删除表内的数据. 2.drop.truncate都是D ...
- 【ASP.NET MVC】 路由机制:命名路由
首先看一下命名路由和没有命名的差别: 命名路由: routes.MapRoute( name: "Test", // Route name url: "code/p/{a ...
- 转:Awesome Vulnerability Research
转:https://github.com/re-pronin/Awesome-Vulnerability-Research Awesome Vulnerability Research
- fetch初步了解
前言 对于ajax请求,我们不仅可以使用XMLHTTPrequest,还可以使用fetch 正文 promise 在使用ajax时,如果想要使得第二个ajax请求调用第一个ajax请求,就得使用在on ...
- 7/31 CSU-ACM2018暑期训练7-贪心
比赛链接 A-CSU - 1588 现在有n堆果子,第i堆有ai个果子.现在要把这些果子合并成一堆,每次合并的代价是两堆果子的总果子数.求合并所有果子的最小代价. Input 第一行包含一个整数T(T ...
- nio案例一:个简单的客户-服务的案例
<Java NIO文档>非阻塞式服务器 原文连接 原文作者:Jakob Jenkov 译者:higher 即使你知道Java NIO 非阻塞的工作特性(如Selector,Channel, ...
- Poj3468 A Simple Problem with Integers (分块)
题面 Poj 题解 区间求和\(+\)区间修改板子,这里用分块写的 #include <cmath> #include <cstdio> #include <cstrin ...
- 【Kruskal】舒适的路线
[codevs1001]舒适的路线 题目描述 Description Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光.Z小镇附近共有N(1<N≤500)个景点(编号为1,2,3,… ...
- 8VC Venture Cup 2016 - Final Round D. Preorder Test 二分 树形dp
Preorder Test 题目连接: http://www.codeforces.com/contest/627/problem/D Description For his computer sci ...