配合服务定位器模式使用JETPACK

介绍服务定位器模式

服务定位器模式(Service Locator Pattern)用在我们想使用 JNDI 查询定位各种服务的时候。考虑到为某个服务查找 JNDI 的代价很高,服务定位器模式充分利用了缓存技术。在首次请求某个服务时,服务定位器在 JNDI 中查找服务,并缓存该服务对象。当再次请求相同的服务时,服务定位器会在它的缓存中查找,这样可以在很大程度上提高应用程序的性能。

服务定位器模式在android上的实现

基于单例模式实现ServiceLocator类

public class ServiceLocator {
    private static final ServiceLocator ourInstance = new ServiceLocator();

    public static ServiceLocator getInstance() {
        return ourInstance;
    }

    private ServiceLocator() {
    }

创建关键的方法,实现“当再次请求相同的服务时,服务定位器会在它的缓存中查找“
举AmapRepository为例,它是一个管理高德地图相关操作和数据的Repository

private volatile AccountRepository accountRepository;

   AccountRepository provideAccountRepository(Context context) {
        synchronized(this) {
            return accountRepository !=null ? accountRepository : createAccountRepository(context);
        }
    }
   private AccountRepository createAccountRepository(Context context){
        Log.i("AccountRepository","createAccountRepository");
        accountRepository = new AccountRepository(...);
        accountRepository.initRepo(context);
        return accountRepository;
    }

通过这种方式,实现了一个服务定位器模式的类。

使用,在Application上初始化

显然这种全局唯一的模式,初始化放在Application 的OnCreate最好不过。

    public AmapRepository getAccountRepository(){
        return ServiceLocator.getInstance().provideAccountRepository(this);
    }
   @Override
    public void onCreate() {
        super.onCreate();
         getAccountRepository();

同时我在Application中创建了一个getAccountRepository()方法,保证只能由Application来初始化和获取AccountRepository的实例,在一定程度上保证了跟应用生命周期的绑定和安全,以及方便在JETPACK上使用

配合JETPACK使用

辅助类FragmentExt

 public static ViewModelFactory getViewModefactory(Fragment fragment)  {
        MainApplication toDoApplication = (MainApplication) fragment.requireContext().getApplicationContext();
        AccountRepository accountRepository = toDoApplication.getAccountRepository();
}
public static ViewModelFactory getViewModefactory(Activity activity)  {
        MainApplication toDoApplication = (MainApplication) activity.getApplicationContext();
        AccountRepository accountRepository = toDoApplication.getAccountRepository();
}

ViewModelFactory工厂

public class ViewModelFactory implements ViewModelProvider.Factory {
    private final AccountRepository accountRepository;
     public ViewModelFactory( AccountRepository accountRepository){
        this.accountRepository = accountRepository;
    }
     @NonNull
    @Override
    public  T create(@NonNull Class modelClass) {
        if(modelClass.isAssignableFrom(AccountViewModel.class)){
            return (T)new AccountViewModel(accountRepository);
        }....
        else{
            throw  new RuntimeException("Unknown ViewModel class");
        }
    }
}

Activity和fragment 创建ViewModel

ViewModelFactory viewModelFactory = FragmentExt.getViewModefactory(this);
        accountViewModel = ViewModelProviders.of(this, viewModelFactory).get(AccountViewModel.class);

总结

这样用ServiceLocator配合JETPACK使用,就可以保证ViewModel里面的这种Repository的资源只初始化一次,而且到处都能复用,既最大程度的解耦了,跟Application生命周期绑定,在任何地方调用都不会出现异常和避免内存泄漏等问题,以及可以很方便地在Serivce这些ViewModel使用不了的地方调用,又保证了数据的统一性。这也是谷歌官方推荐的,ViewModel不直接设计业务逻辑代码,应该封装在里面的repo类。
这样我们就可以安心地在repo类开发我们的逻辑,然后让界面用ViewModel来调用了。

你可能感兴趣的:(配合服务定位器模式使用JETPACK)