实习杂记(21):LocalBroadcastManager的使用、优点在哪里?

LocalBroadcastManager。

       它来自Android 的support包,类名是android.support.v4.content.LocalBroadcastManager,是用来在同一个应用内的不同组件间发送Broadcast的,刚好与我们的场景相符合。同时,它发送的广播只在app内传播,不会泄漏到其他的应用,安全性也有了保证。而且它的使用方式很简单,与普通的广播类似。

其实这里面说的仅仅是数据安全的问题,还有一个非常的优点  也是非常的重要,当然数据安全是最重要的,


在动态广播里面,广播的范围仅仅是自己的activity里面才有用,或者是自己定义的view里面才有用,(虽然一般很少有人在自定义view里面放广播,因为涉及到VIEW更新,因为把UI更新放在这个层级来做,有点虎,),主要说的是范围太小


在静态广播里面,及时APP被关了,如果收到这个消息,还是会有广播的,这个范围太广,就涉及到上面的那个数据安全,而且需要在xml中注册这个接受者,就是receiver属性,这个也不安全,有可能会被进程给干掉,


现在如果有个业务需求是这样的,自定义一个类(工具、视图等),会被重复的使用,或者当前正在使用的有很多个实例,但是从对象这个方面去看,这么多实例中,某个资源同一个时刻仅能有一个实例对象持有这种资源,其他的都只能等,而且这种资源跟用户的操作有很大的关系,举个例子就是:当上一个实例在用这个资源的时候,由于用户的行为新建一个实例需要立马使用这个资源,那么就需要把上一个实例给停了,


看到这里大家肯定会想到使用  单利模式啊,使用static变量啊,使用同步方法啊,等等,

我的意思是想说使用  LocalBroadCastManager也可以解决这个问题,他可以让类对象自己发自己收,其他的实例对象复本也可以收到,然后让他做自己的操作即可,


下面举个例子就是:需要在  ListView中放视频,每个item都是一个视频,但是只能有一个同时在播放,并且用户点击了一个播放没有关闭的情况下,继续点击另外的播放,需要自动把上面的暂停了,并且保存相关状态(记录位置,暂停进度条,显示暂停图标等等),


在这样的背景下,使用LocalBroadCastManager是可以解决问题的,


下面是item那个view自身需要做的处理类的相关代码,这份代码只是demo,而且我没有处理相关状态,只是以释放和播放来解决问题,请不要直接使用。


public class VideoPlayView extends LinearLayout{

private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
public MediaPlayer mediaPlayer;
private boolean isReady = false;
private boolean mIsPlaying = false;
private boolean mIsPause = false;
private Context context;
public String path;
public static String time;
LocalBroadcastManager mLocalBroadcastManager; 
public static final String STATICACTION  = "xxxxx.dynamic.view";




@SuppressLint("NewApi")
public VideoPlayView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
this.context = context;
initView(context);
}
@SuppressLint("NewApi")
public VideoPlayView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
initView(context);
}
public VideoPlayView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initView(context);
}
public VideoPlayView(Context context) {
super(context);
this.context = context;
initView(context);
}
private void initView(Context context) {
LayoutInflater.from(context).inflate(R.layout.public_infoflow_video_play, this, true);
mSurfaceView =(SurfaceView) findViewById(R.id.surfaceview);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(new CustomCallBack());
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
MySetOnClickListener(mSurfaceView);

mLocalBroadcastManager = LocalBroadcastManager.getInstance(context);
IntentFilter intentFilter = new IntentFilter(STATICACTION);
mLocalBroadcastManager.registerReceiver(dynamicReceiver, intentFilter);
}



private void MySetOnClickListener(View view) {
if(view==null){
return ;
}else{
view.setOnClickListener(mClickListener);
}
}

private OnClickListener mClickListener = new OnClickListener(){




@Override
public void onClick(View v) {




Intent intent = new Intent();  
            intent.setAction(STATICACTION);  
            intent.putExtra("msg", getPath());  
            mLocalBroadcastManager.sendBroadcast(intent);


if(path!=null && isReady && !mIsPlaying){
mIsPlaying =true;
mIsPause = false;
isReady = false;
play(0);
}else if(mediaPlayer!=null && mediaPlayer.isPlaying()&& mIsPlaying && !mIsPause ){
mediaPlayer.pause();
mIsPlaying = false;
mIsPause = true;
isReady = true;
release();
}else{
mIsPlaying =true;
mIsPause = false;
isReady = false;
play(0);
}
}

};

private BroadcastReceiver dynamicReceiver = new BroadcastReceiver() {  
        
        @Override  
        public void onReceive(Context context, Intent intent) {  
            if(intent.getAction().equals(STATICACTION)){ 
                String receive_path = intent.getStringExtra("msg");
                if(!path.equals(receive_path)){
                release();
                }
            }  
        }  
    }; 




private class CustomCallBack implements Callback{




@Override
public void surfaceCreated(SurfaceHolder holder) {
isReady = true;
mIsPlaying = false;
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mIsPlaying = false;
release();
}
}
}




@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
release();
mIsPlaying = false;

}




@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsPlaying = false;
release();
mLocalBroadcastManager.unregisterReceiver(dynamicReceiver);
}

}
public String getPath() {
return path;
}
public void play(int position) {
try {
if(mediaPlayer == null){
mediaPlayer = new MediaPlayer();
}
mediaPlayer.reset();
mediaPlayer.setDataSource(path);
mediaPlayer.setDisplay(mSurfaceView.getHolder());
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new PrepareListener(position));

mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {

@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.release();
mIsPlaying = false;
return true;
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

@Override
public void onCompletion(MediaPlayer mp) {
release();
}
});

} catch (Exception e) {
e.printStackTrace();


}

protected void release() {
if(mediaPlayer!=null){
mediaPlayer.setOnErrorListener(null);
try {
mediaPlayer.stop();
mediaPlayer.release();
} catch (Exception e) {
}
}
mediaPlayer = null;
}




private final class PrepareListener implements OnPreparedListener{
private int position;
public PrepareListener(int position){
this.position = position;
}




@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}

}
public void freeResource() {
if(mediaPlayer.isPlaying()){
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
public void setPath(String path) {
this.path = path;
}


}

需要工程包的请留言,暂时代码还没有整理,后面补发。


其实使用这种方式比  单利模式,static变量,同步方法要好些,因为资源最后还是  两份直接轮换,一个current和一个next,双层机制,

音乐播放的时候是使用当前的mediaPlayer和预加载的mediaPlayer,

大视频的无缝播放也是采用两个mediaPlayer来实现的,


而且这种方式附带的在处理相关属性的过程中将会更加的独立,自己处理自己的事多好,如果使用static,判断条件实在太多,而且在退出的时候还需要考虑释放的问题,


当然这种做法也有不好的地方,全屏(如果是使用activity跳转的话)的时候再回来就麻烦了,


w
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值