上篇文章已经讲解了ViewModel的基本原理,了解了原理流程,接下来我们来实现同一个ViewModel如何用于多个Activity之间通信?
下面我先直接贴上代码:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface VMScope {
String scopeName();
}
private static Map<String, VMStore> vMStores = new HashMap<>();
void injectViewModel() {
for (Field field : this.getClass().getDeclaredFields()) {
VMScope annotation = field.getAnnotation(VMScope.class);
VMStore store = null;
if (annotation != null) {
String scopeName = annotation.scopeName();
if (vMStores.containsKey(scopeName)) {
store = vMStores.get(scopeName);
} else {
store = new VMStore();
vMStores.put(scopeName, store);
}
} else {
store = new VMStore();
}
store.bindHost(this);
Class<ViewModel> modelClass = (Class<ViewModel>) field.getType();
ViewModel viewModel = new ViewModelProvider(store, new VMFactory()).get(modelClass);
try {
field.set(this, viewModel);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
class VMFactory implements ViewModelProvider.Factory {
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
try {
return modelClass.newInstance();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return null;
}
}
class VMStore implements ViewModelStoreOwner {
private List<LifecycleOwner> bindTargets = new ArrayList<>();
private ViewModelStore vmStore;
void bindHost(LifecycleOwner host) {
if (!bindTargets.contains(host)) {
bindTargets.add(host);
host.getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
bindTargets.remove(host);
if (bindTargets.isEmpty()) {
vMStores.entrySet().iterator().forEachRemaining(stringVMStoreEntry -> {
if (stringVMStoreEntry.getValue() == VMStore.this) {
vmStore.clear();
vMStores.remove(stringVMStoreEntry.getKey());
}
});
}
}
}
});
}
}
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (vmStore == null) {
vmStore = new ViewModelStore();
}
return vmStore;
}
}
public class ViewModelTestAc extends BaseAc implements Observer<String> {
@VMScope(scopeName = "test")
TestVm testVm;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_viewmodel_test);
Log.d("vmTest", testVm.toString());
}
public void send(View view) {
testVm.stringLiveData.postValue("ViewModelTestAc");
}
@Override
public void onChanged(String s) {
Log.d("ZLX", "ViewModelTestAc=" + s);
}
}