【问题标题】:Architecting FragmentStatePagerAdapter, ViewModel and a Fragment list架构 FragmentStatePagerAdapter、ViewModel 和 Fragment 列表
【发布时间】:2018-06-12 12:27:35
【问题描述】:

简介(以下问题): 根据我的应用程序需求,我需要创建 TabLayout 和扩展 FragmentStatePAgerAdapter 的 ViewPager。 Viewpager 由一种类型的片段列表组成,我们称之为 ListFragment。

每个Fragment 显示一个RecyclerView 列表。

现在进退两难了。我希望实现的是,每个ListFragment 都有一个ViewModel,其中包含ListFragmentLiveData<ArrayList>,同时继续跟踪其自身的片段列表以进行任何更改(Fragment 列表可以是更改(删除/插入/设置))

这是应用程序的图片表示:

App

注意:ListFragment 和 Fragment List 可能会造成混淆。意思是拥有一个ArrayList<ListFragment>,其中每个ListFragment 都有一个ViewModel,其中包含一个LiveData<ArrayList<Object>>

现在事情变得复杂了:

1)我如何为每个 ListFragment 创建一个 ViewModel,我在哪里存储这些 ViewModel?

2)在创建片段列表(具有不确定的大小)时,我在哪里存储列表,以及如何监听其中的变化(例如,删除片段)?

这些问题都是架构师的问题。我对如何实现ViewModelFragmentStatePagerAdapter等有很清楚的了解,但是我很困惑,比如在哪里存储、创建等等。

目前还没有关于架构的假设。它可能是一些 MVVN 或 MVC。

【问题讨论】:

    标签: android android-fragments android-viewpager viewmodel


    【解决方案1】:

    请注意,我对您想要达到的目标有些困惑,但我会试一试。

    我将只有一个 ViewModel,它是在管理所有 List 片段的 Activity 中创建的。然后 ViewModel 将有一个哈希表,用于存储它需要的所有 LiveData<ArrayList<Object>>。作为键,哈希应该使用索引或它所属的片段(最好是后者)。当一个片段应该被删除时,你调用一个 remove 方法从哈希表中删除索引/片段。

    要在 Fragment 中使用 ViewModel,Activity 会将它创建的 ViewModel 注入到 Fragment。这样所有片段共享相同的 ViewModel。请注意执行操作的顺序。

    public class ListsViewModel {
        private HashMap<Integer, MutableLiveData<ArrayList<Object>>> hash = new HashMap<>();
    
        public void setList(int index, ArrayList<Object> newList) {
            if (!hash.containsKey(index)) {
                throw new IllegalStateException("No such list.");
            }
            MutableLiveData<ArrayList<Object>> mutableLiveData = hash.get(index);
            mutableLiveData.setValue(newList);
        }
    
        public LiveData<ArrayList<Object>> getList(int index) {
            if (!hash.containsKey(index)) {
                hash.put(index, new MutableLiveData<ArrayList<Object>>());
            }
            return hash.get(index);
        }
    
        public void flush(Object key) {
            hash.remove(key);
        }
    }
    
    public interface IListFragment {
        public void setViewModel(ListsViewModel listVM, int index);
    }
    
    public class ListFragment extends Fragment implements IListFragment {
    
        private ListsViewModel vm;
        private int key; // might be needed later for cleanup
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Setup fragment
    
            someButton.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    vm.setList(aNewListOrOtherChanges);
                }
            }
        }
    
        @Override
        public void setViewModel(ListsViewModel listVM, int index) {
            this.vm = listVM;
            this.key = index;
            vm.getList(index).observe(this, new Observer<ArrayList<Object>>() {
                @Override
                public void onChanged(@Nullable ArrayList<Object> newList) {
                    // Update UI
                }
            });
        }
    }
    

    【讨论】:

    • 谢谢蒂亚戈。我想知道 - 你为什么选择 Hashtable 而不是矩阵列表?我目前正在使用一个矩阵(ArrayList>),哈希表和矩阵数组都需要一个键,在我们的例子中是索引。
    • 正如您所说,索引作为键(我也在此示例中使用)可以与矩阵一起使用。 hashmap 的优势在于,如果您想将片段用作键,或者将不同的东西与其他键一起存储在其中。但在这种情况下这不是必需的,所以任何一个都应该工作。另一个优点是清除以前的片段不会弄乱密钥始终指向正确数据的顺序。与数组列表一样,删除后的每个条目都会向左移动。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 2018-02-17
    • 1970-01-01
    相关资源
    最近更新 更多