Android仿微信Viewpager-Fragment惰性加载(lazy-loading)

下面是“Android仿微信Viewpager-Fragment惰性加载(lazy-loading)”的完整攻略:

1. 背景介绍

在开发Android App过程中,如果需要使用 Viewpager-Fragment 的方式去实现多个页面的滑动展示效果,会面临一个问题:Viewpager默认是会提前加载所有的Fragment的,这样可能会导致内存占用过大,特别是当页面比较多、内容比较复杂时,更容易出现问题。因此,我们需要实现惰性加载(lazy-loading)的功能,即只加载当前正在显示的Fragment,而不预加载其他Fragment。

2. 解决方案

要实现惰性加载,我们需要进行如下步骤:

  1. 继承FragmentPagerAdapter类
  2. 重写getItem()方法,控制Fragment的加载和销毁
  3. 给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导致内存占用过大的问题。

具体实现方式如下:

  1. 继承FragmentPagerAdapter类
  2. 重写getItem()方法,控制Fragment的加载和销毁
  3. 给Viewpager添加OnPageChangeListener监听器,及时加载当前展示的Fragment

通过以上的代码示例,我们可以更好地理解惰性加载的原理,进而在实际开发中应用到我们的项目中,提高应用的性能和用户体验。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android仿微信Viewpager-Fragment惰性加载(lazy-loading) - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • mantis1.2.19onwindowsserver2012r2datacenter安装 ”

    以下是“mantis1.2.19 on Windows Server 2012 R2 Datacenter 安装”的完整攻略: Mantis 1.2.19 on Windows Server 2012 R2 Datacenter 安装 Mantis是一款开源的缺陷跟踪系统,可以帮助团队更好地管理软件开发过程中的缺陷。本攻略中,我们将介绍如何在Windows …

    other 2023年5月7日
    00
  • 关于spring循环依赖问题及解决方案

    关于Spring循环依赖问题及解决方案 什么是循环依赖? 当两个或多个Bean相互依赖时,我们称之为循环依赖。在Spring中,循环依赖通常会导致一个Bean无法正确创建,如果不加以处理,这将成为Spring框架中的常见错误。 Spring如何解决循环依赖问题? Spring框架提供了三种解决方案,可以帮助我们解决循环依赖问题: 方案一:通过构造函数进行注入…

    other 2023年6月26日
    00
  • 服务器重启不能启动的几种常见解决方法

    当服务器重启后不能正常启动时,可能是由于多种因素引起的,例如操作系统文件损坏、硬件失效、配置错误等。接下来,笔者将为大家介绍几种常见的解决方法。 1. 使用系统恢复模式 操作系统通常都有自带的系统恢复模式,可以修复系统文件错误。具体步骤如下: 重启服务器,在系统启动时,按下对应的快捷键(通常是F8或F12)进入启动菜单界面。 选择“安全模式”或“安全模式带网…

    other 2023年6月27日
    00
  • docker在debianjessie上构建时 “无法找到必需的软件包构建”

    以下是关于“docker在debian jessie上构建时‘无法找到必需的软件包构建’”的完整攻略,过中包含两个示例。 背景 在使用docker构建镜像时,有时会现“无法找到必需的软件包建”的错误。本攻略将介绍如何在debian jess上使用docker构建镜像时解决此问题。 基本原理 在debian jessie上使用docker构建镜像时,可能会出现…

    other 2023年5月9日
    00
  • C/C++语言中的头文件汇总

    C/C++语言中的头文件汇总 头文件是C/C++程序中的重要组成部分,它们包含了程序中所需的函数、变量和类型的声明。在这篇文章中,我们将讨论C/C++语言中的一些常用头文件和它们的作用。 stdio.h stdio.h 是C语言中标准输入/输出头文件,包含了实现输入/输出操作所需的函数和宏。常用的函数包括 printf、scanf、fopen、fclose和…

    other 2023年6月27日
    00
  • C++中拷贝构造函数的使用

    下面我将为您详细讲解C++中拷贝构造函数的使用攻略。 什么是拷贝构造函数 在C++中,拷贝构造函数是一种特殊的构造函数,它用于将一个已有的对象复制到一个新对象中。拷贝构造函数的特殊之处在于它只有一个入参,且该入参为当前类的对象的引用,通常被称为复制构造函数。 拷贝构造函数具有如下特点: 它是一种特殊的构造函数,其函数名为类名。 它只有一个入参,类型为当前类的…

    other 2023年6月26日
    00
  • C语言二叉树常见操作详解【前序,中序,后序,层次遍历及非递归查找,统计个数,比较,求深度】

    C语言二叉树常见操作详解 什么是二叉树 二叉树是一种重要的数据结构,它由节点组成,每个节点最多有两个子节点,左子节点和右子节点。 二叉树具有以下性质: 每个节点最多有两个子节点。 左子节点的值小于父节点的值。 右子节点的值大于父节点的值。 左右子树都是二叉树。 二叉树的基本操作 1.创建一个二叉树 使用递归的方式来创建一个二叉树,每次创建节点时,递归创建左右…

    other 2023年6月27日
    00
  • Python的ini配置文件你了解吗

    当我们在开发Python程序时,尤其是需要读取配置文件时,INI配置文件被广泛使用。下面是从头到尾完整的INI配置文件攻略,包含如何使用Python读取、写入、修改INI配置文件。 什么是INI文件 INI文件是一种纯文本文件格式,通常用作Windows操作系统中应用程序的配置文件。它的基本语法是以节(section)和键值对(key-value)的形式组织…

    other 2023年6月25日
    00
合作推广
合作推广
分享本页
返回顶部