实习杂记(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(){ 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(); @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { release(); mIsPlaying = false; 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;