【问题标题】:How to use same data in two different fragments如何在两个不同的片段中使用相同的数据
【发布时间】:2020-07-14 14:31:06
【问题描述】:

我想在两个不同的片段中使用从 API 响应接收到的数据。

现在我有一个活动和两个片段。

应用启动时,第一个片段中有 API 调用。然后我显示 API 响应的结果。另外,我想在第二个片段中使用相同的结果。我想使用的数据存储在列表中

所以,我的问题是:我是否必须在第一个片段中发出请求并以某种方式将数据传递给第二个片段,或者有一种方法可以在片段之外发出请求,存储结果,然后从两个片段中使用这个结果?

【问题讨论】:

  • 您可以在活动中发出请求,然后将响应传递给捆绑中的两个片段
  • 简单方法:再次发出请求。您要问的是:您可以将数据存储在共享首选项中,或者在从 API 获取数据时使用某种缓存策略。

标签: android android-fragments


【解决方案1】:

如果您以 MVVM 架构模式编写应用程序,我认为您可以使用 Shared ViewModel
Android docs. Share data between fragments
Stack Overflow: Sharing data between fragments using ViewModel

一个活动中的两个或多个片段需要相互通信是很常见的。想象一个主从片段的常见情况,您有一个片段,其中用户从列表中选择一个项目,另一个片段显示所选项目的内容。

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}


public class MasterFragment extends Fragment {
    private SharedViewModel model;

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends Fragment {

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        SharedViewModel model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
        model.getSelected().observe(getViewLifecycleOwner(), { item ->
           // Update the UI.
        });
    }
}

【讨论】:

  • 始终欢迎提供指向潜在解决方案的链接,但请在链接周围添加上下文,以便您的其他用户了解它是什么以及它存在的原因。始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。欲了解更多信息,请查看this
  • 这是一个很好的答案,即使它只是链接。 MVVM 指的是特定架构,因此此链接没有适用的代码。使用 MVVM 架构也是我的建议,因为它是更简洁的方法
  • 感谢您的回答。以前我在没有任何架构模式的情况下编写了我的应用程序。我使用 JAVA。现在我正在尝试使用 MVVM 重构它。我创建了 SharedViewModel。但是在解决我最初的问题时,我偶然发现了另一个问题:如果它们不相互依赖,我如何重用不同片段中的数据?您提供的链接说“一个活动中的两个或多个片段需要相互通信是很常见的”,但这不是我的情况。我想在不同的片段中使用相同的数据,而不是在片段之间切换时向 API 发出新的请求。
  • 但是如果您在两个片段中具有相同的 ViewModel 您可以在两个片段上使用相同的数据。因此,如果在 Fragment A 上加载数据,则将其加载到 SharedViewModel 类中的变量中。然后您可以通过 SharedViewModel 在 Fragment B 中使用相同的变量。所以在代码中,我粘贴到DetailFragment 中回答而不是观察 LiveData 你可以从model.getSelected() 中获取价值并使用它。
  • 非常感谢!我已经创建了包含所有 API 调用的存储库。然后我用一种方法getForecast() 创建了SharedViewModel 来从存储库中检索数据。现在在两个片段中,我使用model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class) 初始化模型,并在我观察到model.getForecast().observe(getViewLifecycleOwner(), forecastData 的变化之后。在此之后,我使用forecastData 进行操作。我对您的建议的理解是否正确?
【解决方案2】:

也许我可以解释一下。您必须创建一个扩展 FragmentStateAdapter 的类,然后您应该创建一个扩展 Fragment 的类,而不是拥有多个类和一个布局。

像这样创建 ClassFragmentPagerAdapter:

public class ClassFragmentPagerAdapter extends FragmentStateAdapter {

public ClassFragmentPagerAdapter (@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
    super(fragmentManager, lifecycle);
}

@NonNull
@Override
public Fragment createFragment(int position) {
    if (position == 0) {
        return new ClassFragment ();
    }
    return new ClassFragment ();
}


@Override
public int getItemCount() {
    return 2;
}

然后创建另一个扩展 Fragment 的 ClassFragment:

public class ClassFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);

    View view = inflater.inflate(R.layout.layout_name, container, false);
    return view;

}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    //do stuff here
}

希望对您有所帮助!快乐编码:)

【讨论】:

    【解决方案3】:

    有几种方法可以解决这个问题。

    解决问题的最简单方法是使用单例。 出于多种原因,我强烈反对这个想法,但大多数情况下,这是启动和运行它的最快方法。

    另一种解决方案是将数据存储在活动的成员中,并通过(activity as MyActivity).myData 访问。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-24
      • 2016-06-04
      • 1970-01-01
      相关资源
      最近更新 更多