Viewpager + fragment + tablayou,每页内存叠加导致内存溢出怎么解决?

嘻嘻嘻_闹 2017-08-24 09:20:25
Viewpager + fragment + tablayout,viewpager用的懒加载

有十几页(十几个fragment,每页布局不一样),

项目运行中发现,每切换一页内存都叠加上去

同一页只叠加一次),十几页翻不到一遍,就内存溢出了,

然后改用FragmentStatePagerAdapter

发现滑动后上一页走ondestroy方法,但内存不减少,

还是会出现原来的问题,不知什么原因大神指教一下!!!
...全文
720 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
嘻嘻嘻_闹 2017-08-31
  • 打赏
  • 举报
回复
问题我解决了,我的思路是: 既然viewpager + tablayout可以跳到指定的索引,肯定viewpager里拿到有fragment的对象那就是viewpager的机制问题了 ,所以并不可能彻底释放,那我就想不清理fragment了,我就清理里面的view,在fragment的ondestroy()的时候,把view制空,然后把view都remove掉,下次切换到在重新初始化,果然解决了
EmMper 2017-08-29
  • 打赏
  • 举报
回复
引用 5 楼 u011273026 的回复:

        private FragmentManager fm;       
         /**
         * 删除内存中所有缓存的fragment,以防止oom
         */
        private void removeAllFragments() {
            if (fm.getFragments() != null) {
                FragmentTransaction ft = fm.beginTransaction();
                for (Fragment fragment : fm.getFragments()) {
                    if (fragment != null) {
                        ft.remove(fragment);
                    }
                }
                ft.commit();
            }
        }
这是我之前写的一个很粗暴的清除内存中fragment的方法。还有一种就是重写FragmentPagerAdapter中的instantiateItem方法。以下是instantiateItem的源码:

    public Object instantiateItem(ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        final long itemId = getItemId(position);
        // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), itemId));
        }
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
        }
        return fragment;
    }
    private static String makeFragmentName(int viewId, long id) {
        return "android:switcher:" + viewId + ":" + id;
    }
无非是通过adapter的container,也就是list view的id和该fragment的position去给这个fragment命了个名。然后在根据这个名字在内存中获取,若为空则新建并存在一个FragmentTransaction的对象中,而且整个方法中只有添加,没有移除。所以你可以重写这个方法,在适当的地方添加移除操作就行了。
第一段代码中的Fragment fm = FragmentActivity.getFragmentManager();
EmMper 2017-08-29
  • 打赏
  • 举报
回复

        private FragmentManager fm;       
         /**
         * 删除内存中所有缓存的fragment,以防止oom
         */
        private void removeAllFragments() {
            if (fm.getFragments() != null) {
                FragmentTransaction ft = fm.beginTransaction();
                for (Fragment fragment : fm.getFragments()) {
                    if (fragment != null) {
                        ft.remove(fragment);
                    }
                }
                ft.commit();
            }
        }
这是我之前写的一个很粗暴的清除内存中fragment的方法。还有一种就是重写FragmentPagerAdapter中的instantiateItem方法。以下是instantiateItem的源码:

    public Object instantiateItem(ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        final long itemId = getItemId(position);
        // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), itemId));
        }
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
        }
        return fragment;
    }
    private static String makeFragmentName(int viewId, long id) {
        return "android:switcher:" + viewId + ":" + id;
    }
无非是通过adapter的container,也就是list view的id和该fragment的position去给这个fragment命了个名。然后在根据这个名字在内存中获取,若为空则新建并存在一个FragmentTransaction的对象中,而且整个方法中只有添加,没有移除。所以你可以重写这个方法,在适当的地方添加移除操作就行了。
怀君 2017-08-25
  • 打赏
  • 举报
回复
内存溢出本来的原因是,申请内存时,没有足够的控件供其使用。感觉应该是每个fragment里面的布局太吃内存导致
EmMper 2017-08-24
  • 打赏
  • 举报
回复
onDestroy了也没用,PagerAdapter中会有指针指向fragment,导致fragment在内存中的地址无法释放。你需要去看FragmentPagerAdapter的源码,如果你能看懂,就会知道怎么解决,如果你看不懂,我告诉你解决方法你也不懂。
ganshenml 2017-08-24
  • 打赏
  • 举报
回复
使用LeakCanary检测下内存的泄漏的原因
嘻嘻嘻_闹 2017-08-24
  • 打赏
  • 举报
回复
没太看懂,还望明示啊

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧