片段之间的共享数据(父列表视图和子列表视图)

Posted

技术标签:

【中文标题】片段之间的共享数据(父列表视图和子列表视图)【英文标题】:Shared data between fragment (parent and child listviews) 【发布时间】:2021-01-01 12:55:08 【问题描述】:

我在fragment 中实现了listview(详细说明如下),我不确定是否有更好的方法。任何人都可以看到我的方法并向我建议在没有代码混乱的情况下实现它的最佳方法。另外,附上所需结果的 gif 动画。

我想做什么,当用户点击详细搜索时,用户将看到一个类别列表,每个类别都有一个子类别,每个类别可以勾选多个项目。用户返回main fragment 后,他将选择的项目将在主fragment 中可用。然后根据用户选择的数据,我可以运行搜索查询。

想要的结果

过滤片段

public class FilterFragment extends Fragment 

    private GalleryViewModel galleryViewModel;
    private ListView lv;
    private List<Cats> categoryList;
    private String[] 

groupArray = "Category1", "Category2", "Category3";
    private String[][] childArray = "Test1", "Test2", "Test3",
            "Video1", "Video2", "Video3", "Audio1", "Audio2", "Audio3";

public View onCreateView(@NonNull LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) 

    View root = inflater.inflate(R.layout.fragment_gallery, container, false);

    lv = (ListView) root.findViewById(R.id.list_view);

    List<Cats> categoryData = null;
    if(getArguments()!=null)
        // data = (String[]) getArguments().getSerializable("strArray");
        categoryList = (List<Cats>)  getArguments().getSerializable("CATEGORY_LIST");
    
    AdapterView.OnItemClickListener clickListener = null;

    // If no data received means this is the first activity
    if (categoryData == null) 
        categoryData = categoryList;
        clickListener = new AdapterView.OnItemClickListener() 
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) 

                FilterFragment newFragment = new FilterFragment();
                Bundle bundle = new Bundle();
                bundle.putSerializable("strArray", childArray[position]);
                newFragment.setArguments(bundle);
                FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
                transaction.replace(R.id.nav_host_fragment, newFragment);
                transaction.addToBackStack(null);
                transaction.commit();
            
        ;
    

    // get data from the table by the ListAdapter
    ListAdapter customAdapter = new ListAdapter(getContext(), R.layout.fragment_filter_item_row, categoryData);

    lv.setAdapter(customAdapter);
    lv.setTextFilterEnabled(true);
    lv.setOnItemClickListener(clickListener);

    return root;


我将通过bundles收回选定的条目到main fragment

【问题讨论】:

【参考方案1】:

您需要一个自定义适配器,这很容易理解

在您的片段中创建一个列表

 public List<Cats> selectedData = new ArrayList<>();

在你的适配器中传递你的片段的引用

YourFragment fragment;
 List<Cats> categoryData;
 public YourAdapter(YourFragment fragmet, List<Cats> categoryData)
     this.fragment = fragment;
     this.categoryData = categoryData;
 

在你的适配器里面的onBindViewHolder

 public void onBindViewHolder(@NonNull ViewHolder holder, int position)
     holder.checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> 
         if(isChecked)
              fragment.selectedData.add(categoryData.get(position));
     );

【讨论】:

实际上还有更多的列表需要维护,像这样的列表还有 3 个。在每个片段内有一个单独的列表并将数据取回主片段的想法使我重新考虑我的初始方法。我想有效地维护选定的数据。你如何建议我将选定的列表移动到主要片段? 如果你想移动 List 那么你最好按照我在答案中的做法,如果你有 3 个不同的列表视图并且它们都有相同的数据,你可以使用一个自定义适配器但是,如果您的数据不同,则需要多个适配器,但是无论数据如何,您都可以在单个适配器中执行此操作,但这会很麻烦,您遇到的问题是列表视图仅检测对其项目的点击,而不是子项目,如果您想让子项正常工作,您肯定需要一个自定义适配器,这听起来可能很麻烦,但是一旦您知道自定义适配器的工作原理,您就会非常高兴。【参考方案2】:

好的,我终于找到了解决方案。我的方法是在片段之间使用 sharedViewModel。

使用 SharedViewModel,我们可以在 Fragment 之间进行通信。如果我们考虑两个片段,两个片段都可以通过它们的活动访问 ViewModel。这是一个预览,我已经上传了一个演示应用程序和代码到 github,所以每个人都可以访问并能够修改片段。

SharedViewModel

public class SharedViewModel extends ViewModel 
    private MutableLiveData<CharSequence> text = new MutableLiveData<>();

    public void setText(CharSequence input) 
        text.setValue(input);
    
    public LiveData<CharSequence> getText() 
        return text;
    

在 Fragment 中获取 sharedViewModel 数据

   @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) 
        super.onActivityCreated(savedInstanceState);
        viewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        viewModel.getText().observe(getViewLifecycleOwner(), new Observer<CharSequence>() 
            @Override
            public void onChanged(@Nullable CharSequence charSequence) 
                editText.setText(charSequence);
            
        );
    

以上是简化的概念,您可以根据需要进行修改。完整代码请参考github。

github:https://github.com/amirdora/FragmentSharedViewModel

【讨论】:

也感谢您对此答案的投入。我很感激。

以上是关于片段之间的共享数据(父列表视图和子列表视图)的主要内容,如果未能解决你的问题,请参考以下文章

如何将可扩展列表视图的选定子视图数据从片段发送到父活动?

进程和线程之间共享和更新列表

视图之间的共享元素转换(不是活动或片段)

如何在作为选项卡的 2 个片段之间共享视图模型

我的共享首选项存储列表视图的数据并检索它不起作用

在 SwiftUI MVVM 中的子视图和父视图之间共享值