美文网首页待写
同一个ViewModel用于多个Activity之间通信

同一个ViewModel用于多个Activity之间通信

作者: ana生 | 来源:发表于2022-03-04 09:01 被阅读0次

    上篇文章已经讲解了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);
        }
    
    }
    

    相关文章

      网友评论

        本文标题:同一个ViewModel用于多个Activity之间通信

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