下面是“Android仿微信Viewpager-Fragment惰性加载(lazy-loading)”的完整攻略:
1. 背景介绍
在开发Android App过程中,如果需要使用 Viewpager-Fragment 的方式去实现多个页面的滑动展示效果,会面临一个问题:Viewpager默认是会提前加载所有的Fragment的,这样可能会导致内存占用过大,特别是当页面比较多、内容比较复杂时,更容易出现问题。因此,我们需要实现惰性加载(lazy-loading)的功能,即只加载当前正在显示的Fragment,而不预加载其他Fragment。
2. 解决方案
要实现惰性加载,我们需要进行如下步骤:
- 继承FragmentPagerAdapter类
- 重写getItem()方法,控制Fragment的加载和销毁
- 给Viewpager添加OnPageChangeListener监听器,以便及时加载当前展示的Fragment
具体实现步骤如下:
2.1 继承FragmentPagerAdapter类
在自己的项目中新建一个PagerAdapter类,继承FragmentPagerAdapter类,并在构造方法中传入FragmentManager和一个Fragment列表。代码如下:
public class PagerAdapter extends FragmentPagerAdapter {
private List<Fragment> mFragments;
public PagerAdapter(@NonNull FragmentManager fm, List<Fragment> fragments) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
mFragments = fragments;
}
@NonNull
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
}
2.2 重写getItem()方法
在上面的代码中,重写了getItem()方法,通过传入的Fragment列表获取当前需要展示的Fragment。注意,这里由于是惰性加载,我们不需要预加载其他的Fragment,因此直接返回当前需要展示的Fragment即可。
2.3 添加OnPageChangeListener监听器
在MainActivity中,我们需要给Viewpager添加一个OnPageChangeListener监听器,以便及时加载当前展示的Fragment。具体代码如下:
public class MainActivity extends AppCompatActivity {
private ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = findViewById(R.id.view_pager);
List<Fragment> fragments = new ArrayList<>();
fragments.add(new Fragment1());
fragments.add(new Fragment2());
fragments.add(new Fragment3());
fragments.add(new Fragment4());
fragments.add(new Fragment5());
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager(), fragments);
mViewPager.setAdapter(pagerAdapter);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
Fragment fragment = getSupportFragmentManager().findFragmentById(mViewPager.getId());
if (fragment instanceof OnPageChangeListener) {
((OnPageChangeListener) fragment).onPageSelected(position);
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
}
在上面的代码中,重写了ViewPager的OnPageChangeListener监听器,当翻页结束后,会调用onPageSelected()方法,我们在这个方法里获取当前展示的Fragment,然后判断它是否实现了OnPageChangeListener接口,如果实现了,就调用它的onPageSelected()方法,以便对当前Fragment进行加载操作。
3. 示例说明
以下是两个示例说明:
3.1 示例1
这个示例中,我们需要实现一个类似微信的聊天界面,其中有两个页面:聊天列表和聊天详情。由于聊天列表可能会很长,因此我们需要惰性加载聊天详情,只有当用户点击某条聊天记录时,才动态地加载聊天详情。具体代码如下:
public class ChatActivity extends AppCompatActivity {
private ViewPager mViewPager;
private List<ChatFragment> mFragments;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
mViewPager = findViewById(R.id.view_pager);
int totalCount = getIntent().getIntExtra("totalCount", 0);
mFragments = new ArrayList<>();
for (int i = 0; i < totalCount; i++) {
mFragments.add(ChatFragment.newInstance("聊天" + (i + 1)));
}
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager(), mFragments);
mViewPager.setAdapter(pagerAdapter);
}
public void switchToChatDetail(int position) {
if (position < 0 || position >= mFragments.size()) {
return;
}
ChatFragment chatFragment = mFragments.get(position);
if (chatFragment != null) {
chatFragment.loadChatDetail();
}
}
}
在上面的代码中,我们新建了一个ChatActivity,其中包含一个ViewPager和一个ChatFragment列表。在创建ChatFragment时,我们传入了聊天的标题,并在里面实现了“惰性”加载聊天详情的功能。具体代码如下:
public class ChatFragment extends Fragment implements OnPageChangeListener {
private TextView mTitle;
private TextView mChatDetail;
private String mChatTitle;
public ChatFragment() {
}
public static ChatFragment newInstance(String param1) {
ChatFragment fragment = new ChatFragment();
Bundle args = new Bundle();
args.putString("title", param1);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mChatTitle = getArguments().getString("title");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_chat, container, false);
mTitle = view.findViewById(R.id.chat_title);
mChatDetail = view.findViewById(R.id.chat_detail);
mTitle.setText(mChatTitle);
return view;
}
public void loadChatDetail() {
mChatDetail.setText("聊天详情");
}
@Override
public void onPageSelected(int position) {
loadChatDetail();
}
}
在上面的代码中,我们实现了OnPageChangeListener接口的onPageSelected()方法,当当前页面被选中时,会自动调用这个方法,然后在这个方法里进行动态加载聊天详情的操作。这样就可以实现惰性加载了。
3.2 示例2
这个示例中,我们需要实现一个类似图片浏览器的应用,可以左右滑动查看多张图片。由于图片可能会很多,因此需要使用惰性加载,只有当前展示的图片才需要加载到内存中。具体代码如下:
public class ImageViewActivity extends AppCompatActivity {
private ViewPager mViewPager;
private List<String> mImageUrls;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_view);
mViewPager = findViewById(R.id.view_pager);
mImageUrls = new ArrayList<>();
mImageUrls.add("https://img0.baidu.com/it/u=1777723668,3364133462&fm=26&fmt=auto&gp=0.jpg");
mImageUrls.add("https://img1.baidu.com/it/u=1871415769,2696643648&fm=26&fmt=auto&gp=0.jpg");
mImageUrls.add("https://img0.baidu.com/it/u=792956869,4176773104&fm=26&fmt=auto&gp=0.jpg");
mImageUrls.add("https://img2.baidu.com/it/u=1168359362,3784133363&fm=26&fmt=auto&gp=0.jpg");
mImageUrls.add("https://img0.baidu.com/it/u=3076408024,2736535225&fm=26&fmt=auto&gp=0.jpg");
List<ImageViewFragment> fragments = new ArrayList<>();
for (int i = 0; i < mImageUrls.size(); i++) {
fragments.add(ImageViewFragment.newInstance(mImageUrls.get(i)));
}
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager(), fragments);
mViewPager.setAdapter(pagerAdapter);
}
}
在上面的代码中,我们新建了一个ImageViewActivity,其中包含一个ViewPager和一个图片Url列表。在创建ImageViewFragment时,我们传入了图片的Url,并在里面实现了“惰性”加载图片的功能。具体代码如下:
public class ImageViewFragment extends Fragment implements OnPageChangeListener {
private ImageView mImageView;
private String mImageUrl;
public ImageViewFragment() {
}
public static ImageViewFragment newInstance(String imageUrl) {
ImageViewFragment fragment = new ImageViewFragment();
Bundle args = new Bundle();
args.putString("imageUrl", imageUrl);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mImageUrl = getArguments().getString("imageUrl");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_image_view, container, false);
mImageView = view.findViewById(R.id.image_view);
return view;
}
@Override
public void onResume() {
super.onResume();
loadImage();
}
private void loadImage() {
Glide.with(this)
.load(mImageUrl)
.into(mImageView);
}
}
在上面的代码中,我们在Fragment的onResume()方法里进行了图片的加载操作,这样就能保证只有当前展示的图片才会被加载。同时,由于我们实现了OnPageChangeListener接口的onPageSelected()方法,因此在用户滑动页面时,也会及时加载新的图片。
4. 总结
通过以上的介绍,我们学习了如何使用惰性加载(lazy-loading)的方式,解决Viewpager预加载过多Fragment导致内存占用过大的问题。
具体实现方式如下:
- 继承FragmentPagerAdapter类
- 重写getItem()方法,控制Fragment的加载和销毁
- 给Viewpager添加OnPageChangeListener监听器,及时加载当前展示的Fragment
通过以上的代码示例,我们可以更好地理解惰性加载的原理,进而在实际开发中应用到我们的项目中,提高应用的性能和用户体验。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android仿微信Viewpager-Fragment惰性加载(lazy-loading) - Python技术站