如何使用视图模型处理片段的配置更改

如何解决如何使用视图模型处理片段的配置更改

我想让我的片段在视图模型配置更改时不会重新加载数据。

所以,我尝试制作一个关于gitHub User的应用程序。 我的主要活动包含“搜索”视图以搜索用户并使用recyclerview显示结果。 当列表中的一个用户单击时,“我的详细信息活动”将显示用户的详细信息,在我的详细信息活动中,我使用“选项卡布局”和“查看传呼机”来显示用户的关注者和关注者。

用于活动的ViewModel效果很好,并且在方向更改时可以保留我的数据。 但是,当我对片段执行相同操作时,当方向改变时,片段会继续重新加载新数据。

这是我的片段 我使用View Model请求数据

public class FollowingFragment extends Fragment {

    public static final String KEY_FOLLOWING = "key_following";
    private RecyclerView recyclerView;
    private FollowingViewModel followingViewModel;
    private FollowingAdapter followingAdapter;

    ShimmerFrameLayout shimmerFrameLayout;

    LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(),LinearLayoutManager.VERTICAL,false);
    ArrayList<FollowingResponse> followingResponse = new ArrayList<>();
    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_following,container,false);
    }

    @Override
    public void onViewCreated(@NonNull View view,@Nullable Bundle savedInstanceState) {
        super.onViewCreated(view,savedInstanceState);
        recyclerView = view.findViewById(R.id.rv_following);
        shimmerFrameLayout = view.findViewById(R.id.shimmer_frame_layout2);

        followingViewModel = ViewModelProviders.of(this).get(FollowingViewModel.class);
        followingAdapter = new FollowingAdapter();
        followingAdapter.setOnItemClickCallback(new FollowingAdapter.OnItemClickCallback() {
            @Override
            public void onItemClicked(FollowingResponse followingResponse) {
                showSelectedItem(followingResponse);
            }
        });

        //this is what i've tried and worked,but my fragment result with double or triple the data.
        if (savedInstanceState == null){

        }
        else {
            followingResponse = savedInstanceState.getParcelableArrayList(KEY_FOLLOWING);
        }


        showRecyclerView();
        getData();
    }

    private void getData() {
        followingViewModel.setDataFollowing(DetailUserActivity.clickedUser);
        followingViewModel.getDataFollowing().observe(getViewLifecycleOwner(),new Observer<ArrayList<FollowingResponse>>() {
            @Override
            public void onChanged(ArrayList<FollowingResponse> followingResponses) {
                shimmerFrameLayout.setVisibility(View.GONE);
                shimmerFrameLayout.stopShimmer();
                followingAdapter.setData(followingResponse);
                followingResponse.addAll(followingResponses);
                recyclerView.setAdapter(followingAdapter);
                followingAdapter.notifyDataSetChanged();
            }
        });
    }
    private void showRecyclerView() {
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(layoutManager);
    }
    @Override
    public void onResume() {
        super.onResume();
        followingViewModel.setDataFollowing(DetailUserActivity.clickedUser);
    }

    private void showSelectedItem(FollowingResponse item) {
        Intent intent = new Intent(getContext(),DetailUserActivity.class);
        intent.putExtra("EXTRA_DATA",item.getLogin());
        startActivity(intent);
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
    }

        @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        outState.putParcelableArrayList(KEY_FOLLOWING,followingResponse);
        super.onSaveInstanceState(outState);
    }
}

详细活动

public class DetailUserActivity extends AppCompatActivity {
    private TextView tvName,tvNickname,tvLocation,tvCompany,tvEmail,tvWebsite;
    private TextView tvCountFollowers,tvCountRepository,tvCountFollowing;
    private ImageView imgProfile;
    ProgressBar progressBar;

    public static String clickedUser;
    UserViewModel userViewModel;

    private ViewPager viewPager;
    TabLayout tabLayout;

    private final String EXTRA_DATA = "EXTRA_DATA";
    private static final String EXTRA_FOLLOW = "extra_follow";

//    Fragment followingFragment;
//    FragmentTransaction transaction;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.detail_user_activity);

//        i've tried this,but when the orientation change,my detail activity force close and throw me to my main activity.
//        if (savedInstanceState != null){
//            followingFragment = getSupportFragmentManager().getFragment(savedInstanceState,KEY_FOLLOWING);
//        } else {
//            followingFragment = new FollowingFragment();
//
//            getSupportFragmentManager().beginTransaction().replace(R.id.tv_view_pager,followingFragment).commit();
//        }

        tvName = findViewById(R.id.tv_item_name);
        tvNickname = findViewById(R.id.tv_item_nickname);
        tvLocation = findViewById(R.id.tv_item_location);
        tvCompany = findViewById(R.id.tv_item_company);
        tvEmail = findViewById(R.id.tv_item_email);
        tvWebsite = findViewById(R.id.tv_item_website);
        imgProfile = findViewById(R.id.img_item_photo);
        tvCountFollowers = findViewById(R.id.tv_count_follower);
        tvCountRepository = findViewById(R.id.tv_count_repo);
        tvCountFollowing = findViewById(R.id.tv_count_following);
        progressBar = findViewById(R.id.progressbar2);

        setForUserData();
        setForTabLayout();
        
    }

    private void setForUserData(){
        Intent detailIntent = getIntent();
        clickedUser = detailIntent.getStringExtra("EXTRA_DATA");
        userViewModel = new ViewModelProvider(this,new ViewModelProvider.NewInstanceFactory()).get(UserViewModel.class);
        userViewModel.setUserUVM(clickedUser);
        userViewModel.getUserUVM().observe(this,new Observer<UserResponse>() {
            @Override
            public void onChanged(UserResponse userResponse) {
                progressBar.setVisibility(View.GONE);
                Glide.with(getApplicationContext())
                        .load(userResponse.getAvatarUrl())
                        .into(imgProfile);
                tvName.setText(userResponse.getLogin());
                tvLocation.setText(userResponse.getLocation());
                tvNickname.setText(userResponse.getName());
                tvCompany.setText(userResponse.getCompany());
                tvEmail.setText(userResponse.getEmail());
                tvWebsite.setText(userResponse.getBlog());

                tvCountRepository.setText(String.valueOf(userResponse.getPublicRepos()));
                tvCountFollowers.setText(String.valueOf(userResponse.getFollowers()));
                tvCountFollowing.setText(String.valueOf(userResponse.getFollowing()));
            }
        });
    }

    
    private void setForTabLayout(){
        tabLayout = findViewById(R.id.tv_tab_layout);
        viewPager = findViewById(R.id.tv_view_pager);
        viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(),tabLayout.getTabCount()));
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
        tabLayout.setTabMode(TabLayout.MODE_FIXED);


        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                viewPager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {
            }
        });
    }

    public class ViewPagerAdapter extends FragmentStatePagerAdapter {
        int totalTab;
        @SuppressWarnings("deprecation")
        ViewPagerAdapter(FragmentManager fragmentManager,int totalTabs) {
            super(fragmentManager);
            this.totalTab = totalTabs;
        }

        @SuppressWarnings("ConstantConditions")
        @NonNull
        @Override
        public Fragment getItem(int position) {
            switch (position){
                case 0:
                    return new FollowersFragment();
                case 1:
                    return new FollowingFragment();
                default:
                    return null;
            }
        }

        @Override
        public int getCount() {
            return totalTab;
        }
    }


//    @Override
//    protected void onSaveInstanceState(@NonNull Bundle outState) {
//       getSupportFragmentManager().putFragment(outState,KEY_FOLLOWING,followingFragment );
//       super.onSaveInstanceState(outState);
//    }
}

im首先尝试解决我的followingFragment,然后对我的FollowerFragment做同样的事情。 我在编程方面真的很新,没有人问..有人可以帮助我解决我的问题,即在方向改变时将数据保持在零散状态吗?

解决方法

followingViewModel = ViewModelProviders.of(this).get(FollowingViewModel.class);

在片段中,打算在onViewCreated()中编写此代码,然后将其写入OnCreate()

onViewCreated()每次方向更改时都会被调用,因此每次方向更改时都会创建视图模型的新实例,从而使viewmodel重新加载数据

,

如果您只需要为FollowingViewModel加载一次数据,那么这样做的好地方应该放在视图模型的构造函数中,这样就不必担心片段的方向更改

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-