介绍服务定位器模式
服务定位器模式(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 extends ViewModel> T create(@NonNull Class<T> 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来调用了。
网友评论