如何解决如何使用视图模型处理片段的配置更改
我想让我的片段在视图模型配置更改时不会重新加载数据。
所以,我尝试制作一个关于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 举报,一经查实,本站将立刻删除。