我应该在哪里调用Rest API [英] Where should I call Rest API in fragment

查看:80
本文介绍了我应该在哪里调用Rest API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用3个片段的底部导航.在Home-fragment上,我请求API提取数据并在回收器视图中显示,我的问题是每当我切换片段并再次进入Home-fragment时,它都会重新创建布局,并且再次从API提取数据,我只想加载一次应用启动时

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

  @Nullable@Override公共视图onCreateView(@NonNull LayoutInflater充气机,@ Nullable ViewGroup容器,@ Nullable捆绑包saveInstanceState){视图view = inflater.inflate(R.layout.home_fragment,container,false);//返回inflater.inflate(R.layout.home_fragment,container,false);sharedPrefManager =新的SharedPrefManager(getActivity());locationTrack = new LocationTrack(getActivity());buildGoogleApiClient();fusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());getUserLatLng();setUp(view);netWorkCall();返回视图} 

HomeActivity默认加载家庭片段

  if(savedInstanceState == null){片段片段= null;片段=新的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){片段片段= null;开关(itemId){案例R.id.action_home:片段=新的HomeFragment();休息;案例R.id.action_profile:如果(sharedPrefManager.getAuthority()){片段=新的ProfileFragment();} 别的 {SDConstant.switchActivity(this,LoginScreen.class);}休息;案例R.id.action_calculator:如果(sharedPrefManager.getAuthority()){片段=新的CalculatorFragment();} 别的 {SDConstant.switchActivity(this,LoginScreen.class);}休息;}//替换片段if(fragment!= null){FragmentTransaction ft = getSupportFragmentManager().beginTransaction();ft.replace(R.id.content_frame,fragment,"home").addToBackStack("Home");ft.commitAllowingStateLoss();//ft.commitNow();}}} 

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

解决方案

首先,在 onViewCreated 而不是 onCreateView 内执行此调用:

  sharedPrefManager = new SharedPrefManager(getActivity());locationTrack = new LocationTrack(getActivity());buildGoogleApiClient();fusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());getUserLatLng();setUp(view);netWorkCall();//此调用必须删除,如稍后说明 

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

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

您可以在此处上了解更多内容..>

您的实现可能看起来像这样(改编自链接中的示例):

 公共类MyViewModel扩展了ViewModel {私有MutableLiveData< List< User>用户;公共LiveData< List< User>>getUsers(){如果(用户==空){users =新的MutableLiveData< List< User>>();loadUsers();}回头客;}私人void loadUsers(){//进行异步操作以获取用户.}} 

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

  MyViewModel模型= new ViewModelProvider(getViewLifecycleOwner()).get(MyViewModel.class);model.getUsers().observe(getViewLifecycleOwner(),users-> {//更新用户界面}); 

不要为此感到不知所措.实际上,它所做的是相对简单的.ViewModel可以保留配置更改.这意味着,如果您旋转手机,则不会再次调用loadUsers请求-与在底部导航选项卡之间切换相同.当然,如果片段被销毁,ViewModel也将被销毁(然后调用onCleared函数).

LiveData用户只是一个简单观察者的名字.可变意味着您可以设置一个值,getUsers()返回一个不可更改的LiveData,这意味着您只能读取其值.当为LiveData对象设置值时,将通知其订阅者.您可以想象它像LiveData是由使用ViewModel的Fragment实现的接口.并且,一旦您获取了数据,就会调用此接口函数.有关处理LiveData的更多信息在此处进行了解释,您一定要检查一下.

因此,如果尚未加载用户,则ViewModel将在您开始观察getUsers时调用loadUsers.如果已加载它们,则返回当前值.

哦,要添加LiveData和ViewModel-> 在这里说明:)

希望这很有帮助.我知道很多,但是相信我,值得花时间!

I'm using Bottom-navigation with 3 fragments. On Home-fragment I'm requesting API to fetch data and show in recycler-view my problem is whenever I switch fragments and come again to Home-fragment it's recreating the layout and again its fetch data from API I want to load only one time when app launch

This is where I call API in the fragment

  @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 to load home-fragment by default

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();
            }
        }

bottom-navigation click listener

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();
            }
    }
    }

Please guide me solution How to solve this re-creation API call

解决方案

First off, perform this calls inside onViewCreated instead of 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

Why? Because onCreateView should just return the fragments UI. OnViewCreated is called directly afterwards and this is the place to do some stuff.

No to get to your problem. The best way for you to solve this would be using a ViewModel from the architecture components in conjunction with LiveData.

You can read more on this topic here.

Your implementation could look like this (adapted the example from the link):

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.
    }
}

In your onViewCreated you can do something lik this:

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

Don't feel overwhelmed by this. What it does in reality is relatively simple. The ViewModel survives configuration changes. Meaning if you rotate your phone the loadUsers request won't be invoked again - same with switching between bottom navigation tabs. Of course If the fragment is destroyed, the ViewModel does also get destroyed (the function onCleared is invoekd then).

The LiveData users is just a fancy name for a simple observer. Mutable means that you can set a value, getUsers() returns a non mutable LiveData, this means you can only read its value. When you set a value to a LiveData object, it's subscriber will be notified. You can imagine it like the LiveData is an interface implmented by your Fragment which is using the ViewModel. And this interfaces function is invoked once you have fetched data. More info on dealing with LiveData is explained here you should definitely check it out.

So the ViewModel will invoke loadUsers once you start observing getUsers if the Users have not been loaded yet. If they have been loaded, the current value is returned.

Oh and to add LiveData and ViewModel -> it's explained here :)

Hope this was helpful. I know it is alot but trust me it is worth investing the time!

这篇关于我应该在哪里调用Rest API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆