介紹服務(wù)定位器模式
服務(wù)定位器模式(Service Locator Pattern)用在我們想使用 JNDI 查詢定位各種服務(wù)的時候旭贬。考慮到為某個服務(wù)查找 JNDI 的代價很高燥翅,服務(wù)定位器模式充分利用了緩存技術(shù)骑篙。在首次請求某個服務(wù)時,服務(wù)定位器在 JNDI 中查找服務(wù)森书,并緩存該服務(wù)對象靶端。當(dāng)再次請求相同的服務(wù)時,服務(wù)定位器會在它的緩存中查找凛膏,這樣可以在很大程度上提高應(yīng)用程序的性能杨名。
服務(wù)定位器模式在android上的實(shí)現(xiàn)
基于單例模式實(shí)現(xiàn)ServiceLocator類
public class ServiceLocator {
private static final ServiceLocator ourInstance = new ServiceLocator();
public static ServiceLocator getInstance() {
return ourInstance;
}
private ServiceLocator() {
}
創(chuàng)建關(guān)鍵的方法,實(shí)現(xiàn)“當(dāng)再次請求相同的服務(wù)時猖毫,服務(wù)定位器會在它的緩存中查找“
舉AmapRepository為例台谍,它是一個管理高德地圖相關(guān)操作和數(shù)據(jù)的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;
}
通過這種方式,實(shí)現(xiàn)了一個服務(wù)定位器模式的類吁断。
使用趁蕊,在Application上初始化
顯然這種全局唯一的模式,初始化放在Application 的OnCreate最好不過仔役。
public AmapRepository getAccountRepository(){
return ServiceLocator.getInstance().provideAccountRepository(this);
}
@Override
public void onCreate() {
super.onCreate();
getAccountRepository();
同時我在Application中創(chuàng)建了一個getAccountRepository()方法掷伙,保證只能由Application來初始化和獲取AccountRepository的實(shí)例,在一定程度上保證了跟應(yīng)用生命周期的綁定和安全又兵,以及方便在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 創(chuàng)建ViewModel
ViewModelFactory viewModelFactory = FragmentExt.getViewModefactory(this);
accountViewModel = ViewModelProviders.of(this, viewModelFactory).get(AccountViewModel.class);
總結(jié)
這樣用ServiceLocator配合JETPACK使用任柜,就可以保證ViewModel里面的這種Repository的資源只初始化一次卒废,而且到處都能復(fù)用,既最大程度的解耦了宙地,跟Application生命周期綁定摔认,在任何地方調(diào)用都不會出現(xiàn)異常和避免內(nèi)存泄漏等問題,以及可以很方便地在Serivce這些ViewModel使用不了的地方調(diào)用宅粥,又保證了數(shù)據(jù)的統(tǒng)一性参袱。這也是谷歌官方推薦的,ViewModel不直接設(shè)計業(yè)務(wù)邏輯代碼粹胯,應(yīng)該封裝在里面的repo類蓖柔。
這樣我們就可以安心地在repo類開發(fā)我們的邏輯,然后讓界面用ViewModel來調(diào)用了风纠。