美文网首页
在Android中使用动态代理实现类似系统ServiceMang

在Android中使用动态代理实现类似系统ServiceMang

作者: 三十二蝉 | 来源:发表于2018-03-10 16:41 被阅读56次

    概述

    在工程中,为了清晰划分接口与实现的概念,我们通过会使用interface和实现了这个interface的类。在变量声明的时候,声明变量的类型为interface的类型,但是实际赋值的是实现了interface的类的实例。从而达到静态代理的目的。
    在实现的项目开发中,我们可能希望代理的功能更强大,特别是在多模块项目中。我们使用两层嵌套的静态代理来模仿ServiceManger管理一系列后台服务,具体流程如下:

    • 定义一个App全局的Service的管理接口: 抽象类AppService
    public abstract class AppService {
    protected static AppService instance;
    public static Context context;
    
    public AppService() {
    }
    
    @NonNull
    public static <T> T getService(Class<T> clazz) {
      return instance.getServiceImpl(clazz);
    }
    
    @NonNull
    public static <T> T getService(Class<T> clazz, boolean isNeedNewObject) {
      return instance.getServiceImpl(clazz, isNeedNewObject);
    }
    
    @NonNull
    protected abstract <T> T getServiceImpl(Class<T> var1);
    
    @NonNull
    protected abstract <T> T getServiceImpl(Class<T> var1, boolean var2);
    }
    

    AppService的抽象功能是后台服务路由。AppService是一个抽象类,所以具体的路由实现是由子类来完成的。但是AppService有一个AppService静态变量instance,一旦子类实例化并赋值给instance,我们就可以通过如下方式调用后台服务:

      AppService.getService(ILauch.class).goLogin();
    

    这里的AppService其实和系统的ServiceManager类似,管理了一系列的后台服务。下面看下他的实现类:

    public final class AppServiceImp extends AppService {
      private static HashMap<String, Object> services = new HashMap<>();
      private AppServiceImp() {
      }
      public synchronized static YoucaiService getInstance() {
        if (instance == null)
          instance = new AppServiceImp();
        return instance;
      }
    
      @Override
      protected @NonNull <T> T getServiceImpl(Class<T> clazz) {
        String className = clazz.getName();
        if (!services.containsKey(className)) {
          createService(className);
        }
        return (T) services.get(className);
      }
    
      @Override
      protected @NonNull <T> T getServiceImpl(Class<T> clazz, boolean isNeedNewObject) {
        String cn = clazz.getName();
        if (!services.containsKey(cn)) {
          createService(cn);
        }
        if (!isNeedNewObject) {
          return (T) services.get(cn);
        } else {
          try {
            return (T) (services.get(cn).getClass().newInstance());
          } catch (InstantiationException e) {
            return null;
          } catch (IllegalAccessException e) {
            return null;
          }
        }
      }
    
      /*根据类型路由到对应的服务实现类*/      
      private void createService(String cName) {
        if (ILaunch.class.getName().equals(cName)) {
          services.put(cName, LaunchImp.getInstance());
        } else if (IDownload.class.getName().equals(cName)) {
           ...
        } 
      }
    
    }
    

    这里我们在Application初始化的时候,调用AppServiceImpl.getInstance()方法初始化AppService,这时候AppService的instance已经是AppServiceImpl的实例。

    如何在多模块项目中使用AppService的这套机制

    先假设项目有如下模块:base模块(library模块),mobile模块(Application模块,可以打apk,会依赖其他个人模块),other模块(其他功能模块,会依赖base模块)。

    • base模块:我们在base模块中,定义AppService这个抽象类以及ILaunch等服务接口。这样在other模块中就可以通过AppService和ILaunch接口对服务进行访问。
    • mobile模块:主模块,可打包整个项目。AppServiceImpl,LaunchImpl都是在这里实现的。
    • other模块:业务功能模块,依赖base模块,会调用服务。通过如下方式调用:AppService.getService(ILauch.class).goLogin()

    使用动态代理实现

    上述使用了静态代理的方法实现了类似ServiceManager的机制。下面介绍改用动态代理的方式实现。动态代理就不需要Service服务分发这一步了,直接使用注解来表示不同的服务。

    • 首先还是在base中定义AppService接口
    public interface AppService {
    //******************** 账号相关业务接口 **************************************
    @Account
    void goLogin();
    @Account
    void getUserInfo(CSCallback<CSModel> callback);
    @Account
    boolean isLogin();
    
    
    //******************** 下载相关业务接口 ***********************************
    @Download
    void goDownload(String url);
    }
    

    这里将服务的类型转用了注解的形式表示。

    • 在mobile模块中实现APPServiceImpl
      public class AppServiceImpl {
      private DownloadManager downloadManager;
      private LaunchManager launchManager;
      
      public AppServiceImpl() {
        this.downloadManager = new DownloadManager();
        this.launchManager = new LaunchManager();
      }
      
      public <T> T create(final Class<T> service) {
        validateServiceInterface(service);
      
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
            new InvocationHandler() {
      
              @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
                  throws Throwable {
                // If the method is a method from Object then defer to normal invocation.
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                return proxyRoute(method, args);
              }
            });
      }
      
      /** 服务,以及具体的服务方法代理*/
      private <T> T proxyRoute(Method method, @Nullable Object[] args) {
        if (method.isAnnotationPresent(Account.class)) {
          if (method.getName().equals("isLogin")) {
            return (T) launchManager.isLogin();
          }else if (method.getName().equals("getUserInfo")) {
              launchManager.getUserInfo((CSCallback<CSModel>) args[0]);
          }
        }else if (method.isAnnotationPresent(Download.class)) {
          if (method.getName().equals("goDownload")) {
            return (T)certificationManager.goDownload((String) args[0]);
          }
        }
        return null;
      }
      
      
      static <T> void validateServiceInterface(Class<T> service) {
        if (!service.isInterface()) {
          throw new IllegalArgumentException("API declarations must be interfaces.");
        }
        // Prevent API interfaces from extending other interfaces. This not only avoids a bug in
        // Android (http://b.android.com/58753) but it forces composition of API declarations which is
        // the recommended pattern.
        if (service.getInterfaces().length > 0) {
          throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
        }
      }
      }
      

    上述代码已经实现了AppService从Client接口到具体Service、具体Service方法的代理。下面只要创建DownloadManager、LaunchManager实现具体方法即可。

    • 为了在other模块使用,我们在base模块定义AppServiceClient抽象类:
    public abstract class  AppServiceClient {
    
      private static AppService appService;
    
      public static AppService getAppService() {
        return appService;
      }
      public abstract AppService bindAppService();
    

    在mobile模块Application初始化的时候,初始化一个AppServiceClientImpl:

    public class  AppServiceClientImpl extend AppServiceClient {
      public static init() {
        if(null == appService) {
          new AppServiceClientImpl();
        }
      }
      private AppServiceClientImpl(){
        getAppService();
      };
    
      public AppService bindAppService() {
        if (null == appService) {
          AppServiceImpl serviceImpl = new AppServiceImpl();
          appService = serviceImpl.create(AppService.class);
        }
        return appService;
      }
    
    AppServiceClientImpl.init();
    

    在other模块调用方式如下:

    AppServiceClient.getAppService().goLogin();
    

    相关文章

      网友评论

          本文标题:在Android中使用动态代理实现类似系统ServiceMang

          本文链接:https://www.haomeiwen.com/subject/kufbfftx.html