先来通过ijkplayer中的IjkMediaPlayer的设计,来看一下适配器模式是什么样的,首先先看一下IMediaPlayer这个接口,下面是代码
public interface IMediaPlayer {
int MEDIA_INFO_UNKNOWN = 1;
int MEDIA_INFO_STARTED_AS_NEXT = 2;
int MEDIA_INFO_VIDEO_RENDERING_START = 3;
int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700;
int MEDIA_INFO_BUFFERING_START = 701;
int MEDIA_INFO_BUFFERING_END = 702;
int MEDIA_INFO_NETWORK_BANDWIDTH = 703;
int MEDIA_INFO_BAD_INTERLEAVING = 800;
int MEDIA_INFO_NOT_SEEKABLE = 801;
int MEDIA_INFO_METADATA_UPDATE = 802;
int MEDIA_INFO_TIMED_TEXT_ERROR = 900;
int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901;
int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;
int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;
int MEDIA_INFO_AUDIO_RENDERING_START = 10002;
int MEDIA_INFO_AUDIO_DECODED_START = 10003;
int MEDIA_INFO_VIDEO_DECODED_START = 10004;
int MEDIA_INFO_OPEN_INPUT = 10005;
int MEDIA_INFO_FIND_STREAM_INFO = 10006;
int MEDIA_INFO_COMPONENT_OPEN = 10007;
int MEDIA_INFO_VIDEO_SEEK_RENDERING_START = 10008;
int MEDIA_INFO_AUDIO_SEEK_RENDERING_START = 10009;
int MEDIA_INFO_MEDIA_ACCURATE_SEEK_COMPLETE = 10100;
int MEDIA_ERROR_UNKNOWN = 1;
int MEDIA_ERROR_SERVER_DIED = 100;
int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;
int MEDIA_ERROR_IO = -1004;
int MEDIA_ERROR_MALFORMED = -1007;
int MEDIA_ERROR_UNSUPPORTED = -1010;
int MEDIA_ERROR_TIMED_OUT = -110;
void setDisplay(SurfaceHolder var1);
void setDataSource(Context var1, Uri var2) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
@TargetApi(14)
void setDataSource(Context var1, Uri var2, Map var3) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
void setDataSource(FileDescriptor var1) throws IOException, IllegalArgumentException, IllegalStateException;
void setDataSource(String var1) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
String getDataSource();
void prepareAsync() throws IllegalStateException;
void start() throws IllegalStateException;
void stop() throws IllegalStateException;
void pause() throws IllegalStateException;
void setScreenOnWhilePlaying(boolean var1);
int getVideoWidth();
int getVideoHeight();
boolean isPlaying();
void seekTo(long var1) throws IllegalStateException;
long getCurrentPosition();
long getDuration();
void release();
void reset();
void setVolume(float var1, float var2);
int getAudioSessionId();
MediaInfo getMediaInfo();
/** @deprecated */
@Deprecated
void setLogEnabled(boolean var1);
/** @deprecated */
@Deprecated
boolean isPlayable();
void setOnPreparedListener(IMediaPlayer.OnPreparedListener var1);
void setOnCompletionListener(IMediaPlayer.OnCompletionListener var1);
void setOnBufferingUpdateListener(IMediaPlayer.OnBufferingUpdateListener var1);
void setOnSeekCompleteListener(IMediaPlayer.OnSeekCompleteListener var1);
void setOnVideoSizeChangedListener(IMediaPlayer.OnVideoSizeChangedListener var1);
void setOnErrorListener(IMediaPlayer.OnErrorListener var1);
void setOnInfoListener(IMediaPlayer.OnInfoListener var1);
void setOnTimedTextListener(IMediaPlayer.OnTimedTextListener var1);
void setAudioStreamType(int var1);
/** @deprecated */
@Deprecated
void setKeepInBackground(boolean var1);
int getVideoSarNum();
int getVideoSarDen();
/** @deprecated */
@Deprecated
void setWakeMode(Context var1, int var2);
void setLooping(boolean var1);
boolean isLooping();
ITrackInfo[] getTrackInfo();
void setSurface(Surface var1);
void setDataSource(IMediaDataSource var1);
public interface OnTimedTextListener {
void onTimedText(IMediaPlayer var1, IjkTimedText var2);
}
public interface OnInfoListener {
boolean onInfo(IMediaPlayer var1, int var2, int var3);
}
public interface OnErrorListener {
boolean onError(IMediaPlayer var1, int var2, int var3);
}
public interface OnVideoSizeChangedListener {
void onVideoSizeChanged(IMediaPlayer var1, int var2, int var3, int var4, int var5);
}
public interface OnSeekCompleteListener {
void onSeekComplete(IMediaPlayer var1);
}
public interface OnBufferingUpdateListener {
void onBufferingUpdate(IMediaPlayer var1, int var2);
}
public interface OnCompletionListener {
void onCompletion(IMediaPlayer var1);
}
public interface OnPreparedListener {
void onPrepared(IMediaPlayer var1);
}
}
该接口定义了很多方法,但是实际你可能只需要其中的某一些方法,所以接着设计了一个抽象类AbstractMediaPlayer,下面是该类的代码
public abstract class AbstractMediaPlayer implements IMediaPlayer {
private OnPreparedListener mOnPreparedListener;
private OnCompletionListener mOnCompletionListener;
private OnBufferingUpdateListener mOnBufferingUpdateListener;
private OnSeekCompleteListener mOnSeekCompleteListener;
private OnVideoSizeChangedListener mOnVideoSizeChangedListener;
private OnErrorListener mOnErrorListener;
private OnInfoListener mOnInfoListener;
private OnTimedTextListener mOnTimedTextListener;
public AbstractMediaPlayer() {
}
public final void setOnPreparedListener(OnPreparedListener listener) {
this.mOnPreparedListener = listener;
}
public final void setOnCompletionListener(OnCompletionListener listener) {
this.mOnCompletionListener = listener;
}
public final void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) {
this.mOnBufferingUpdateListener = listener;
}
public final void setOnSeekCompleteListener(OnSeekCompleteListener listener) {
this.mOnSeekCompleteListener = listener;
}
public final void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener) {
this.mOnVideoSizeChangedListener = listener;
}
public final void setOnErrorListener(OnErrorListener listener) {
this.mOnErrorListener = listener;
}
public final void setOnInfoListener(OnInfoListener listener) {
this.mOnInfoListener = listener;
}
public final void setOnTimedTextListener(OnTimedTextListener listener) {
this.mOnTimedTextListener = listener;
}
public void resetListeners() {
this.mOnPreparedListener = null;
this.mOnBufferingUpdateListener = null;
this.mOnCompletionListener = null;
this.mOnSeekCompleteListener = null;
this.mOnVideoSizeChangedListener = null;
this.mOnErrorListener = null;
this.mOnInfoListener = null;
this.mOnTimedTextListener = null;
}
protected final void notifyOnPrepared() {
if (this.mOnPreparedListener != null) {
this.mOnPreparedListener.onPrepared(this);
}
}
protected final void notifyOnCompletion() {
if (this.mOnCompletionListener != null) {
this.mOnCompletionListener.onCompletion(this);
}
}
protected final void notifyOnBufferingUpdate(int percent) {
if (this.mOnBufferingUpdateListener != null) {
this.mOnBufferingUpdateListener.onBufferingUpdate(this, percent);
}
}
protected final void notifyOnSeekComplete() {
if (this.mOnSeekCompleteListener != null) {
this.mOnSeekCompleteListener.onSeekComplete(this);
}
}
protected final void notifyOnVideoSizeChanged(int width, int height, int sarNum, int sarDen) {
if (this.mOnVideoSizeChangedListener != null) {
this.mOnVideoSizeChangedListener.onVideoSizeChanged(this, width, height, sarNum, sarDen);
}
}
protected final boolean notifyOnError(int what, int extra) {
return this.mOnErrorListener != null && this.mOnErrorListener.onError(this, what, extra);
}
protected final boolean notifyOnInfo(int what, int extra) {
return this.mOnInfoListener != null && this.mOnInfoListener.onInfo(this, what, extra);
}
protected final void notifyOnTimedText(IjkTimedText text) {
if (this.mOnTimedTextListener != null) {
this.mOnTimedTextListener.onTimedText(this, text);
}
}
public void setDataSource(IMediaDataSource mediaDataSource) {
throw new UnsupportedOperationException();
}
}
然后通过IjkMediaPlayer extends AbstractMediaPlayer ,通过IMediaPlayer mMediaPlayer = new IjkMediaPlayer()来使用需要用到的相应的功能,这样就可以只实现自己需要的方法了,不和原始的接口打交道,避免了不必要的浪费。其实这就是一种适配器模式,确切的说叫做接口的适配器模式 ,下面说一下什么是接口的适配器模式。
接口的适配器模式:有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这 个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。
除了接口的适配器模式外,还有两种,一种是类的适配器模式,另一种是对象的适配器模式。
类的适配器模式:先看一下下面的代码
public class Source {
public void method1(){
System.out.println("this is original method");
}
}
public interface Targetable {
/**
* 与原类中的方法相同
*/
public void method1();
/**
*新类的方法
*/
public void method2();
}
public class Adapter extends Source implements Targetable{
@Override
public void method2() {
System.out.println("this is the targetable method");
}
}
public class AdapterTest {
public static void main(String[] args) {
Targetable targetable = new Adapter();
targetable.method1();
targetable.method2();
}
}
其实就是将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题 。
对象的适配器模式:
基本思路和类的适配器模式相同,只是将 Adapter 类作修改,这次不继承 Source 类,而是持有 Source 类的实例,以达到解决兼容性的问题。下面看下代码的实现:
public class Source {
public void method1(){
System.out.println("this is original method");
}
}
public interface Targetable {
/**
* 与原类中的方法相同
*/
public void method1();
/**
*新类的方法
*/
public void method2();
}
public class Wrapper implements Targetable{
private Source mSource;
public Wrapper(Source source){
super();
this.mSource = source;
}
@Override
public void method1() {
System.out.println("this is the targetable method ");
}
@Override
public void method2() {
mSource.method1();
}
}
public class AdapterTest {
public static void main(String[] args) {
Source source = new Source();
Targetable target = new Wrapper(source);
target.method1();
target.method2();
}
}
上面所述就是适配器模式的三种模式,开发中也会经常遇到。