组件间通信是什么
我们通常把一个module认为是一个组件,组件间通信是两个不存在依赖关系的module间进行通信的方式。在Android中由于module间不可以双向依赖,所以如果你想调用某个没有依赖关系的组件的服务往往是做到的,而组件间通信正好可以解决这样的问题。组件间通信在组件化和插件化中扮演了重要角色。
手机用户可以点这里查看
组件间通信实现
实现组件间通信的三个关键点,接口下沉,反射调用,代理访问。
接口下沉
要访问一个不存在依赖关系的module,直接通过调用具体类是不行的,具体类是在各自module里定义并实现的,所以是无法直接访问到的,只能通过接口访问。所以需要定义一个公共组件,让其他组件都依赖于它,需要暴露服务给第三方调用的组件在公共组件里去定义它们的接口,并且在各自组件内部去实现,第三方只能通过这些接口来访问其提供的服务。
反射调用
在公共组件定义其他组件对外服务的接口,那么通过这些接口要能够访问到其他组件才行。因为公共组件会被其他组件依赖,没办法直接调用其他组件的方法,所以只能通过反射调用。但是也不可能说每个方法都通过反射来调用,这样太麻烦,而且代码会变得很不好维护,所以其他组件需要实现一个统一接口,把所有需要对外暴露的方法都在里面定义,并以在公共组件定义的接口返回。这样公共组件只需要通过反射访问到这个统一接口,就可以访问到其对外提供的所有服务。
代理访问
前面说了公共组件可以通过反射访问到其他组件对外暴露的一个统一接口,进而访问其提供的所有服务。那么第三方组件想访问这些服务,就需要通过公共组件间接调用实现,因为公共组件只是一个代理对象,真正提供服务的是各个组件,所以这里就用到了代理机制。组件间通信需要通过公共组件代理实现。
说了这么多,我们看下一个简单的框架图
假如位于ModuleA的ClientA想访问位于ModuleB的ServiceB,那么它需要通过公共组件提供的ProxyB实现。ProxyB会先通过反射访问到ComponentB,ComponentB就是ModuleB实现的对外提供服务的统一接口,然后再通过ComponentB访问到ServiceB。
接下来,我们直接上代码,通过代码会把问题变得更加清晰。
前期准备
假设现在有一个项目包含了视频组件video和音乐组件music。这两个module不存在依赖关系,其中video组件提供直播和短视频服务,music组件提供听歌和唱歌服务,现在要想在视频组件调用音乐组件提供的服务,在音乐组件调用视频组件提供的服务。我们看下要怎么实现。
定义基础库
组件间通信需要通过代理接口实现,所以需要引入一个公用的基础库来定义一些公共接口。假如这个基础库叫baselib,让video和music组件都依赖baselib。在baselib中定义如下接口:
1.IMusicComponent:音乐组件接口,对外提供音乐组件相关的服务,新增服务需要在这里定义。
public interface IMusicComponent {
/**
* 获取听歌服务
* @return
*/
IListenerService getListenerService();
/**
* 获取唱歌服务
* @return
*/
ISingService getSingService();
}
2.IListenerService:听歌服务
public interface IListenerService {
void playMusic();
void pauseMusic();
}
3.ISingService:唱歌服务
public interface ISingService {
void startSing();
void stopSing();
}
4.IVideoComponent:视频组件接口,对外提供视频组件相关的服务,新增服务需要在这里定义。
public interface IVideoComponent {
/**
* 获取直播服务
* @return
*/
ILiveService getLiveService();
/**
* 获取短视频服务
* @return
*/
IShortVideoService getShortVideoService();
}
5.ILiveService:直播服务
public interface ILiveService {
void enterLive();
void leaveLive();
}
6.IShortVideoService:短视频服务
public interface IShortVideoService {
void startRecord();
void stopRecord();
}
7.IComponentFactory:组件工厂接口,定义项目中所有对外提供服务的组件
public interface IComponentFactory {
IVideoComponent createVideoComponent();
IMusicComponent createMusicComponent();
}
8.ComponentFactory:组件工厂,负责各个组件的创建。这里需要注意因为baselib不依赖于各个组件所以只能通过反射的方式来创建组件。
public class ComponentFactory implements IComponentFactory{
private IVideoComponent mVideoComponent;
private IMusicComponent mMusicComponent;
private ComponentFactory() {
}
private static class Holder{
private static final ComponentFactory sInstance = new ComponentFactory();
}
public static ComponentFactory getInstance(){
return Holder.sInstance;
}
@Override
public synchronized IVideoComponent createVideoComponent() {
if(mVideoComponent == null){
try {
//MusicComponent是music模块的类,通过反射拿到该类
Class<?> clazz = Class.forName("com.hyh.video.VideoComponent");
//获取有参构造函数
Constructor c= clazz.getConstructor(Context.class);
//通过有参构造创建对象
mVideoComponent = (IVideoComponent) c.newInstance(MyApplication.getApplication());
} catch (Exception e) {
e.printStackTrace();
}
}
return mVideoComponent;
}
@Override
public synchronized IMusicComponent createMusicComponent() {
if(mMusicComponent == null){
try {
//MusicComponent是music模块的类,通过反射拿到该类
Class<?> clazz = Class.forName("com.hyh.music.MusicComponent");
//获取有参构造函数
Constructor c= clazz.getConstructor(Context.class);
//通过有参构造创建对象
mMusicComponent = (IMusicComponent) c.newInstance(MyApplication.getApplication());
} catch (Exception e) {
e.printStackTrace();
}
}
return mMusicComponent;
}
}
视频组件
实现对外提供的服务
1.LiveService:直播服务
public class LiveService implements ILiveService {
private Context mContext;
public LiveService(Context context) {
mContext = context;
}
@Override
public void enterLive() {
Toast.makeText(mContext,"开始直播",Toast.LENGTH_SHORT).show();
}
@Override
public void leaveLive() {
Toast.makeText(mContext,"结束直播",Toast.LENGTH_SHORT).show();
}
}
2.ShortVideoService:短视频服务
public class ShortVideoService implements IShortVideoService {
private Context mContext;
public ShortVideoService(Context context) {
mContext = context;
}
@Override
public void startRecord() {
Toast.makeText(mContext,"开始录制",Toast.LENGTH_SHORT).show();
}
@Override
public void stopRecord() {
Toast.makeText(mContext,"结束录制",Toast.LENGTH_SHORT).show();
}
}
3.VideoComponent:视频组件实现类,通过它创建所提供的服务
public class VideoComponent implements IVideoComponent {
private Context mContext;
private ILiveService mLiveService;
private IShortVideoService mShortVideoService;
public VideoComponent(Context context) {
mContext = context;
}
@Override
public synchronized ILiveService getLiveService() {
if(mLiveService == null){
mLiveService = new LiveService(mContext);
}
return mLiveService;
}
@Override
public synchronized IShortVideoService getShortVideoService() {
if(mShortVideoService == null){
mShortVideoService = new ShortVideoService(mContext);
}
return mShortVideoService;
}
}
实现访问音乐组件的服务代理
要访问其他组件的服务需要通过代理实现。
1.ListenerServiceProxy:通过听歌服务代理访问音乐组件的听歌服务
public class ListenerServiceProxy implements IListenerService {
private IListenerService mListenerService;
public ListenerServiceProxy() {
mListenerService = ComponentFactory.getInstance().createMusicComponent().getListenerService();
}
@Override
public void playMusic() {
mListenerService.playMusic();
}
@Override
public void pauseMusic() {
mListenerService.pauseMusic();
}
}
2.SingServiceProxy:通过唱歌服务代理访问音乐组件的唱歌服务
public class SingServiceProxy implements ISingService {
private ISingService mSingService;
public SingServiceProxy() {
mSingService = ComponentFactory.getInstance().createMusicComponent().getSingService();
}
@Override
public void startSing() {
mSingService.startSing();
}
@Override
public void stopSing() {
mSingService.stopSing();
}
}
音乐组件
实现对外提供的服务
1.ListenerService:听歌服务
public class ListenerService implements IListenerService {
private Context mContext;
public ListenerService(Context context) {
mContext = context;
}
@Override
public void playMusic() {
Toast.makeText(mContext,"开始播歌",Toast.LENGTH_SHORT).show();
}
@Override
public void pauseMusic() {
Toast.makeText(mContext,"暂停播歌",Toast.LENGTH_SHORT).show();
}
}
2.SingService:唱歌服务
public class SingService implements ISingService {
private Context mContext;
public SingService(Context context) {
mContext = context;
}
@Override
public void startSing() {
Toast.makeText(mContext,"开始唱歌",Toast.LENGTH_SHORT).show();
}
@Override
public void stopSing() {
Toast.makeText(mContext,"停止唱歌",Toast.LENGTH_SHORT).show();
}
}
3.MusicComponent:音乐组件实现类,通过它创建所提供的服务
public class MusicComponent implements IMusicComponent {
private Context mContext;
private ListenerService mListenerService;
private SingService mSingService;
public MusicComponent(Context context) {
mContext = context;
}
@Override
public synchronized IListenerService getListenerService() {
if(mListenerService == null){
mListenerService = new ListenerService(mContext);
}
return mListenerService;
}
@Override
public ISingService getSingService() {
if(mSingService == null){
mSingService = new SingService(mContext);
}
return mSingService;
}
}
实现访问视频组件的服务代理
要访问其他组件的服务需要通过代理实现。
1.LiveServiceProxy:通过直播服务代理访问视频组件的直播服务
public class LiveServiceProxy implements ILiveService {
private ILiveService mLiveService;
public LiveServiceProxy() {
mLiveService = ComponentFactory.getInstance().createVideoComponent().getLiveService();
}
@Override
public void enterLive() {
mLiveService.enterLive();
}
@Override
public void leaveLive() {
mLiveService.leaveLive();
}
}
2.ShortVideoServiceProxy:通过短视频服务代理访问视频组件的短视频服务
public class ShortVideoServiceProxy implements IShortVideoService {
private IShortVideoService mShortVideoService;
public ShortVideoServiceProxy() {
mShortVideoService = ComponentFactory.getInstance().createVideoComponent().getShortVideoService();
}
@Override
public void startRecord() {
mShortVideoService.startRecord();
}
@Override
public void stopRecord() {
mShortVideoService.stopRecord();
}
}
总结
组件间通信主要用到的技术是反射和代理接口。只要理解了反射和代理在其中发挥的作用,组件间通信其实也不难。
源码
github地址
如果对你有帮助希望帮忙点个赞哈