【问题标题】:Where should I call Rest API in fragment我应该在哪里调用片段中的 Rest API
【发布时间】:2020-09-22 02:03:51
【问题描述】:

我正在使用带有 3 个片段的底部导航。在 Home-fragment 我请求 API 来获取数据并在回收器视图中显示我的问题是每当我切换片段并再次回到 Home-fragment 它正在重新创建布局并再次从 API 获取数据我只想加载一次应用启动时

这是我在片段中调用 API 的地方

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

        View view = inflater.inflate(R.layout.home_fragment, container, false);
       // return inflater.inflate(R.layout.home_fragment, container, false);
        sharedPrefManager = new SharedPrefManager(getActivity());
        locationTrack = new LocationTrack(getActivity());

        buildGoogleApiClient();
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());
        getUserLatLng();
        setUp(view);
        netWorkCall();
        return view;
    }

HomeActivity 默认加载 home-fragment

if (savedInstanceState == null) {
            Fragment fragment = null;
            fragment = new HomeFragment();

            if (fragment != null) {
                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                ft.add(R.id.content_frame, fragment, "home").addToBackStack("Home");
                ft.commit();
            }
        }

底部导航点击监听器

private void displaySelectedScreen(int itemId) {

     Fragment fragment = null;

    switch (itemId) {

     case R.id.action_home:
                    fragment = new HomeFragment();
                    break;
                case R.id.action_profile:
                    if (sharedPrefManager.getAuthority()) {
                        fragment = new ProfileFragment();
                    } else {
                        SDConstant.switchActivity(this, LoginScreen.class);

                    }
                    break;
                case R.id.action_calculator:
                    if (sharedPrefManager.getAuthority()) {
                        fragment = new CalculatorFragment();
                    } else {
                        SDConstant.switchActivity(this, LoginScreen.class);
                    }
                    break;
            }
            //replacing the fragment
            if (fragment != null) {
                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                ft.replace(R.id.content_frame, fragment, "home").addToBackStack("Home");
                ft.commitAllowingStateLoss();
                //ft.commitNow();
            }
    }
    }

请指导我解决方案如何解决此重新创建 API 调用

【问题讨论】:

  • 如果你的应用遵循SingleActivity-MultipleFragments模式,那么你可以在你的Activity中调用API相关的东西。您可以在片段中漫游,在这些片段中使用Activity 获取的数据,并根据需要更新数据。

标签: java android android-fragments fragment retrofit2


【解决方案1】:

首先,在onViewCreated而不是onCreateView中执行这个调用:

sharedPrefManager = new SharedPrefManager(getActivity());
locationTrack = new LocationTrack(getActivity());

buildGoogleApiClient();
fusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());
getUserLatLng();
setUp(view);
netWorkCall(); //this call has to be removed as explained later

为什么?因为 onCreateView 应该只返回片段 UI。之后直接调用 OnViewCreated,这是做一些事情的地方。

不解决您的问题。解决此问题的最佳方法是将架构组件中的 ViewModel 与 LiveData 结合使用。

您可以阅读有关此主题的更多信息here

您的实现可能如下所示(改编自链接中的示例):

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<User>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

在您的 onViewCreated 中,您可以执行以下操作:

MyViewModel model = new ViewModelProvider(getViewLifecycleOwner()).get(MyViewModel.class);
model.getUsers().observe(getViewLifecycleOwner(), users -> {
    // update UI
});

不要为此感到不知所措。它在现实中的作用相对简单。 ViewModel 在配置更改后仍然存在。这意味着如果您旋转手机,将不会再次调用 loadUsers 请求 - 与在底部导航选项卡之间切换相同。当然如果 Fragment 被销毁,ViewModel 也会被销毁(函数 onCleared 被 invoekd 调用)。

LiveData 用户只是简单观察者的一个花哨名称。可变意味着你可以设置一个值,getUsers() 返回一个不可变的 LiveData,这意味着你只能读取它的值。当您为 LiveData 对象设置值时,将通知其订阅者。你可以想象它就像 LiveData 是一个由你的 Fragment 实现的接口,它使用 ViewModel。一旦您获取数据,就会调用此接口函数。有关处理 LiveData is explained here 的更多信息,您一定要查看。

因此,如果用户尚未加载,一旦您开始观察 getUsers,ViewModel 就会调用 loadUsers。如果它们已被加载,则返回当前值。

哦,添加 LiveData 和 ViewModel -> it's explained here :)

希望这对您有所帮助。我知道这很多,但相信我,值得投入时间!

【讨论】:

  • 谢谢你的回答兄弟,我需要学习Lifecycle ViewModel 有没有其他方法可以解决这个问题。
  • 我会调查的。很久没有在没有 ViewModel 的情况下做过这样的事情了
  • 好的,兄弟,如果你有其他方法,请更新我,它将对我更有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-06
  • 2018-10-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多