ViewPager刷新难题详解

作者:李旺成

6、《匠人如神》

【书评】

Honda小车创办者-本田(Honda)宗一郎讲述他什么从最底部的徒弟,到创立世界头号公司,分享了东瀛更加的“匠人之道”。

“匠人精神”和德意志联邦共和国工业创制精神,是多年来回升到国家意识层面去热烈谈论的话题。那背后,恰恰体现出了所有社会的浮躁心情。扶桑的“匠人文化”,是从点滴细节做起,把一件事情完了丰盛深刻,讲求对细节极致追求和把控。

回望当下境内为何要大谈“匠人”精神?匠人精神在中原是或不是具备土壤?大家谈到眼前境内的创业和经纪氛围万分浮躁,那种对于成功、财富的敏捷追求和最好渴望恰恰突显出了一个国家国民的不安全感。

在日本、德意志联邦共和国,也许有几代人经营一个职业,做到十分的科班精深的千姿百态,是因为那个国度空气、公司CEO的环境要绝对更成熟,而老百姓对生存富有足够的安全感,才足以心无旁骛的去举办深度商量。

而在现今的神州,从社会氛围到CEO理念都不曾给经营者或者个人构建这样一种钻研的”安全氛围“。火速奔跑、急迅成长仍然是我们今天社会的主旋律。我们只可以考虑到的还有医治、教育、保证和养老的题材,福利种类的不齐全,让芸芸众生除了靠自己多赚取,别无他法。

书友分享了一个有关骆驼和兔子的管制理论:外资集团因为经营条件良好、管理水平较高,更像骆驼,他们早就有了很好的储贷,几天不吃不喝也可以。他们体贴战略管理和商店文化管理。

而中国信用社需求速度和赢利,如同兔子,不能和骆驼一样存储食品,必须一边跑一边找食品,否则就会饿死。在管理上只要盲目标用管骆驼的措施来治本兔子,兔子一定会饿死。

那让我们反思:在收受海外先进的经纪管理理念的时候,要怎么样因地制宜、对症发药,结合实际情况,不盲从,格外考验管理者的小聪明。

比如硅谷对于姿色管理的意见就算是大家的科普肯定,但位于初创公司上是还是不是合宜?

一个每一日都要直面生存的商号,究竟谈人才管理更恰当,如故谈产品的精益创业更好?

“匠人”精神听起来很美,在那些土壤上是或不是能成功先不饿死,再来谈精进?初创公司要过了一个怎样的妙法之后,才能称为脱离了”生存基本线“,可以更加多的做战略聚焦?管理者面临更加多的先进经验借鉴和家乡文化适应的难点,就如《创业维艰》作者说的那么:没有良方,唯有实践。

从大前研一著的《思考的技巧中》,给大家留下了一个思考题:

  1. 您觉得你们公司理应解决的最大题材是哪些?

  2. 借使您的岗位比前天高两级,为了化解这一个难题,你首先会做什么样?

  3. 然而你的铺面为何现在不这么做啊?

请举出集团不这样做的多少个理由,再并对准每一个说辞写出,假若你的职位比现行高两级,你会什么打败?

让我们品尝进步自己的管理维度,来磨练一下融洽的思维能力和缓解难题的能力。


跟着在正儿八经花艺老师-Perry先生的带领下,体验了一把“匠人精神”-做两件很精致的手工多肉花艺饰品。

看起来小小的花艺饰品,做起来手工复杂程度当先了大件花艺著作。大家一边惊叹要做“匠人”不便于,另一方面也对这样投入的日子、精力的著述在市面上应有怎样定价发出了座谈。

“匠人”在神州的泥土上要解决生存再到升高的标题,还有漫长长路要走。希望在未来市面腾飞到早晚成熟程度,能够包容接受越来越多商业形象存在,而不仅只是把高速追求利润作为公司的终极目的。

若果你也有趣味涉足线下活动,或者是想参与我们思想题的思考和答复,可以私信给自身留言,共同啄磨。谢谢!


isa-拥有14年品牌营销经验

品牌顾问/创业者/自由撰稿人/旅行爱好者/一生学习实践者

每一年读书超越100本,对一切和美关于的事物深深着迷,努力把人生的多面都活的美好!

一经本文对您有援救,欢迎喜欢、关怀自我,更欢迎私信越来越多交换和任性的打赏哦!

时间:2016年5月3日


(男士们都虚心的躲在一方面)

三、FragmentPagerAdapter

中秋小长假的结尾一天,和一群书友们在联合走过了美好的一个晚上,调换读到好书的心得,一起上学制作多肉花艺。书友们进献了好多盘算干货。

ViewPager刷新难题详解

互换和享受的意义,在于我们得以从别人那边上学从另一个角度来对待同一个事物,了然思想的力量,学会“多一种沉思格局”。同时也能砥砺大家的思考力和表明能力。

简介

地方通过使 getItemPosition() 方法重返 POSITION_NONE
到达数据源变化(也就是调用
notifyDataSetChanged())时,刷新视图的目标。不过当我们选取 Fragment 作为
ViewPager 的 Item 时,就须要多着想部分了,而且貌似是行使
FragmentPagerAdapter 或者 FragmentStatePager艾达pter。

此间不展开商讨 FragmentPagerAdapter 与 FragmentStatePagerAdapter
的异议和动用情状了,感兴趣的可以看看那篇作品:FragmentPagerAdapter与FragmentStatePagerAdapter区别

上面先来探视使用 FragmentPagerAdapter 时,怎样在数据源暴发变化时,刷新
Fragment 或者动态改变 Items 的数量。

4、《创业维艰》

【书评】

固然如此书友并不都是创业者,可是在众多管理书籍中自己依然采取了这一本。

二〇一八年首先次读那本书的时候我要么一个职业首席营业官人,小编在经营管理、人才拔取、人员管理上的智慧就让我得到累累。

再读的时候,我的角色暴发了转移,成为了一名苦逼的创业者,对于小编毫不掩饰的赤裸裸自己在创业路上的懦弱、胆怯、绝望、苦逼的像狗,同时对于团结做错的决定、坦白认可“是自家无能”的那种心思有了越多的共鸣。

那本书真实的描述了一个创业者经历的高高低低、无数个忧伤折磨的不眠之夜。最让自家感动的是小编对于职工的坦诚,对于团结做错决定、公司处于悬崖边缘的坦白。

国内的集团家多数喜爱粉饰太平,明明苦逼到明日就发不出薪金了,前天还要和职工说形势大好。不敢于直面困境,也不乐意认同那是因为自己的韬略失误而导致的结果。错失了很多打成一片的难得机会。

并且小编提议的田间管理逻辑本身很有同感:他提议了人→产品→利润的治本逻辑。

认为一名供销社创办人、一名管事人,首先需要管理的是人,即包蕴了人才的选择、激励、培训、管理,也包蕴了官员自己的复明定位和管理:不躲避难点、不逃避权利,勇气、能力和信念的管制。

就算大家并不是各种人都要变成创业者,但倘诺能换个角度,站在老总、董事长、COO的角度去看待工作中的难点,培育那样的思维能力,中度不等、眼界也会迥然分歧。

方案:清除 FragmentManager 中缓存的 Fragment

先看功能:

FragmentPagerAdapter数据源刷新演示1

心想事成上图效果的主要代码:
1、FPagerAdapter1Activity.java

private void refresh() {
    if (checkData()) return;
    mDataList.set(0, 7); // 修改数据源
    mPagerAdapter.updateData(mDataList); // 通知 Adapter 更新
}

private void add() {
    mDataList.add(7);
    mPagerAdapter.updateData(mDataList);
}

private void delete() {
    if (checkData()) return;
    mDataList.remove(0);
    mPagerAdapter.updateData(mDataList);
}

private void clear() {
    if (checkData()) return;
    mDataList.clear();
    mPagerAdapter.updateData(mDataList);
}

2、FPagerAdapter1.java

public class FPagerAdapter1 extends FragmentPagerAdapter {

    private ArrayList<Fragment> mFragmentList;
    private FragmentManager mFragmentManager;

    public FPagerAdapter1(FragmentManager fm, List<Integer> types) {
        super(fm);
        this.mFragmentManager = fm;
        mFragmentList = new ArrayList<>();
        for (int i = 0, size = types.size(); i < size; i++) {
            mFragmentList.add(FragmentTest.instance(i));
        }
        setFragments(mFragmentList);
    }

    public void updateData(List<Integer> dataList) {
        ArrayList<Fragment> fragments = new ArrayList<>();
        for (int i = 0, size = dataList.size(); i < size; i++) {
            Log.e("FPagerAdapter1", dataList.get(i).toString());
            fragments.add(FragmentTest.instance(dataList.get(i)));
        }
        setFragments(fragments);
    }

    private void setFragments(ArrayList<Fragment> mFragmentList) {
        if(this.mFragmentList != null){
            FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
            for(Fragment f:this.mFragmentList){
                fragmentTransaction.remove(f);
            }
            fragmentTransaction.commit();
            mFragmentManager.executePendingTransactions();
        }
        this.mFragmentList = mFragmentList;
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return this.mFragmentList.size();
    }

    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }
}

3、思路分析
地点的代码思路很粗略,就是当数据源暴发变化时,先将 FragmentManger
里面所有缓存的 Fragment 全体革除,然后再一次创制,那样达到刷新视图的目标。

不过,那样做有一个毛病,那就是会招致不需要的荒废,会潜移默化属性。还有就是必须运用一个
List 缓存所有的 Fragment,那也得占用不少内存…

思路挺不难,那里不再赘述,那看看有没有哪些可以优化的。


尝试环境准备

看看实验环境,上代码:

private void initData() {
    // 数据源
    mDataList = new ArrayList<>(5);
    mDataList.add("Java");
    mDataList.add("Android");
    mDataList.add("C&C++");
    mDataList.add("OC");
    mDataList.add("Swift");

    // 很简单的一个 PagerAdapter
    this.mContentVP.setAdapter(mPagerAdapter = new PagerAdapter() {
        @Override
        public int getCount() {
            return mDataList.size();
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = View.inflate(SimpleDemoActivity.this, R.layout.item_vp_demopageradapter, null);
            TextView pageNumTV = (TextView) view.findViewById(R.id.tv_pagenum);
            pageNumTV.setText("DIY-PageNum-" + mDataList.get(position));
            container.addView(view);
            return view;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }

    });
}

ViewPager 的 Item:item_vp_demopageradapter.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">
    <ImageView
        android:id="@+id/iv_img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/activity_horizontal_margin"
        android:src="@mipmap/ic_launcher" />
    <!-- 用于显示文本,数据更新体现在这里 -->
    <TextView
        android:id="@+id/tv_pagenum"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/activity_horizontal_margin"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="DIY-Page-" />
</LinearLayout>

很简短的代码,并且加了诠释,直接往下看实验。

书友们推荐的图书分享:

小结

至于 ViewPager 数据源刷新比较费心的地方是从数据源中删除数据的情事,那和
ViewPager
的兑现格局有关,我们在化解该难点的时候要分具体情状来拔取两样的方案。

地点提供的方案也不是一揽子的,还有不少不足,假诺你在使用的进度中相遇了难题,那么请举报给自家,大家一道完善。

此处根本是商讨关于 ViewPager 数据源刷新的标题,关于 ViewPager
的事无巨细使用不是本文重点,那里就不涉及了。

管住就是限量集团的重任,并鼓舞和团体人力资源去贯彻那些义务。-Peter·德鲁克。

优化:通过 Tag 获取缓存的 Fragment

先看作用:

FragmentPagerAdapter数据源刷新演示2

从地方的动图上可以看来,更新某一个 Fragment
小意思,清空数据源的时候也不曾,添加当然也没怎么难点;请小心删除的出力,即便,目标Fragment 确实从 ViewPager
中移除了,但是滑动前面的页面会发现出现了数码错乱。

剖析一下优化的笔触

先来打探 FragmentPagerAdapter 中是哪些管理 Fragment 的,这里涉及到
FragmentPagerAdapter 中的 instantiateItem() 方法:

@Override
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;
}

从源码中得以观察在从 FragmentManager 中取出 Fragment 时调用了
findFragmentByTag() 方法,而那些 Tag 是由 makeFragmentName()
方法生成的。继续往下得以看出每一个 Fragment 都打上了一个标签(在
mCurTransaction.add() 方法中)。

也就是说是 FragmentManager 通过 Tag 找相应的 Fragment,从而达到缓存
Fragment 的目标。若是得以找到,就不会创建新的 Fragment,Fragment 的
onCreate()、onCreateView() 等格局都不会再度调用。

优化的思路就有了:
首先,内需缓存所有 Fragment 的 Tag,代码如下:

private List<String> mTagList; // 用来存放所有的 Tag

// 生成 Tag
// 直接从 FragmentPageAdapter 源码里拷贝 Fragment 生成 Tag 的方法
private String makeFragmentName(int viewId, int index) {
    return "android:switcher:" + viewId + ":" + index;
}

// 将 Tag 缓存到 List 中
@Override
public Object instantiateItem(ViewGroup container, int position) {
    mTagList.add(position, makeFragmentName(container.getId(),
            (int) getItemId(position)));
    return super.instantiateItem(container, position);
}

其次,在更新 Fragment 时,使用相应的 Tag 去 FragmentManamager
中找相应的 Fragment,若是存在,就径直更新,代码如下:

public void update(int position, String str) {
    Fragment fragment = mFragmentManager.findFragmentByTag(mTagList.get(position));
    if (fragment == null) return;
    if (fragment instanceof FragmentTest) {
        ((FragmentTest)fragment).update(str);
    }
    notifyDataSetChanged();
}

该格局要求活动在 Fragment 中提供。

最后,对此动态改变 ViewPager 中 Fragment
的数据,借使是加上,那不要主要留意的;不过删除有点棘手。

在上边的动态上看看,删除一个 Fragment
后会出现混乱,那里没有进一步去商量了,那里仅提供一个演示供参考(这一个示例代码有标题,仅供参考)

public void remove(int position) {
    mDataList.remove(position);
    isDataSetChange = true;
    Fragment fragment = mFragmentManager.findFragmentByTag(mTagList.get(position));
    mTagList.remove(position);
    if (fragment == null) {
        notifyDataSetChanged();
        return;
    }
    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
    fragmentTransaction.remove(fragment);
    fragmentTransaction.commit();
    mFragmentManager.executePendingTransactions();
    notifyDataSetChanged();
}

注意:
以此”优化“示例,仅仅适用于在只必要创新某个 Fragment 的场景,关于动态删除
Fragment,该”优化“方案并不适用,也不引进应用。

5、《旅行,人生最有价值的投资》

【书评】

随后顶级投资人-吉米·罗吉尔斯去环游世界,并在旅行的种种进程中都意识投资机遇。是的,标题标“投资”,真的就是指真金白银、得到回报的投资。

吉米·罗吉尔斯,带着比自己小一三个月纪的女对象,骑着保时捷摩托车,在90年代,环游世界。正因为不是搭乘飞机、不是追随旅行团,而是使用了骑摩托那种最接地气的不二法门,让吉米在出行每个国家的时候,得以中远距离的洞察每个国家、每个城市的经济现象。

在上海,他感触到了华夏的愈演愈烈,从黑市英镑交易上看出了投资机遇;在南美,他发现立刻的乌拉圭就好像欧洲的瑞士联邦,成为了金融活跃的区域,看到了前途划算升高的火候。

俺们常说提高眼界和格局有几个艺术:读万卷书、行万里路,阅人无数。旅行也被认为是开发眼界的极品办法。分享这本书的姊姊是一个有类似20年的资深背包客、大致走遍整个世界的显赫驴友,她提议的远足管理思路极度令人深思:

纵深旅行:

吉米·罗吉尔斯如果不是使用骑摩托的点子,他的投资赢得可能要少得多。深度旅行让大家有机遇去和当地人深度调换,明白当地风俗和社会、经济前行景色。能用深度旅行的思辨方法来规划和管理的远足,将会在开阔视野、培育洞察力等方面有更大的擢升。

参考

ViewPager
详解(二)—详解四大函数

pagerAdapter arrayList 数据清空,Item
不销毁的bug解决

ViewPager刷新单个页面的章程
ViewPager动态加载、删除页面
ViewPager+Fragment滑动界面,并做延迟加载【新版】
有关ViewPager的数量更新难点总计
Viewpager+fragment数据更新难题浅析
追根究底源码解决android疑难有关难点1-Viewpager之notifyDataSetChanged无刷新
缓解fragment+viewpager第二次进入的时候没有数量的题材
FragmentPagerAdapter刷新fragment最完善解决方案
Viewpager+fragment数据更新难题分析
FragmentPagerAdapter与FragmentStatePagerAdapter区别

6、《非暴力沟通》

【书评】

人类社会离不开互换,每日大家必要和上下级关系、和伴侣、孩子、家人联系,和爱侣联系。然而比较人类思想指数级的飞速提升,我们利用的关联工具-语言,在向上变革的速度上还跟不上。

也就是说,大家在用一个针锋绝对古老的工具-语言,去调换大家大脑中更为连忙反应的意识形态。在这些进程中,势必会暴发音信的散失、表明不标准、新闻不对称等题材。

《非暴力沟通》的小编给大家提供了一套很好的工具、体系来治本大家的语言表明能力,让大家在寻常生活沟通中,少一些言语暴力。

心怀管理也是大家各类人天天都要直面的标题。语言之所以会充满暴力在于大家鞭长莫及很好的田间管理大家的心怀,才会在对最亲的人说话的时候怒发冲冠;在职场中不可以将压力转移,变成了埋怨和不满……

采用书中作者提供的工具,可以更好的管理大家的牵连进程中的心境,去了解两者的差异,使联系尤其的短平快。

一、PagerAdapter介绍

先看作用图

PageAdapter 使用示例

1、《关于跑步,我说的实际是……》(新疆版)

【书评】

村上春树作为一个大小说家,本书叙述了她从一个恰恰起步的业余爱好者,如何通过设定目的、科学标准的陈设,而改为了一个职业马拉松运动员。村上通过她的经历告诉我们,大家即便早期不是专业人士,但经过正确的宏图和部署,水滴石穿的努力,都可以在某一个领域正官专业人员。

他给协调定义一个众所周知的靶子,具备强烈的民用分析和优势战略聚焦。书中介绍了怎么统筹跑步以及跑步的历程,详细、科学且客观的安顿;有阶段性且有意志的私有保管,实干型且坚韧的执行力。

在跑步那件工作上,村上有极为不利的治本艺术:

1)目的设定:

用作一个女作家,身体的花费是大幅度的,必须加强体质磨炼和人身管理,令肉体素质更好的卓绝他的写作寿命。明确的对象是大家锲而不舍做一件业务的最大驱动力。

2)过程管理:

颇为不利的奔走布署:如科学的餐饮陈设,渐渐递加的路程安插,每一周有严俊的行程规定,下雨天的替代操练陈设等……

3)心境管理:

村上曾在弥利坚、非洲、日本等多地跑动,每个地点的环境对于跑者的心境都有很大的熏陶,村上运用科学的精选音乐的主意,器重平衡和调试,在奔跑的历程中为自己成立“沉浸式”的长空。

用作日本艺术学界的常青树,村上春树跑马拉松,既不是为着搏人眼球,也不是为了在爱人圈被人点赞,他有极为分明的目的和严格科学的进度管理。

俺们有点朋友都有小跑或者健身的习惯,可是大家发现百折不挠是最难堪的工作。由内心真正的对象驱动,是我们得以百折不回下去的说辞。百折不回自己钟爱的业务并为之付出努力,像村上春树那样,从史学家成为了马拉松选手,成为多一个版本的“斜杠青年”。

四、FragmentStatePagerAdapter

先看作用:

FragmentStatePagerAdapter数据源刷新演示

这一期的主旨是探讨和“经营管理”有关的书本,书友们大饱眼福的经纪管理涵盖万分广的限定,有分外丰富的内蕴:从个体保管、目的管理、家庭经营、情感管理、时间管理、旅行管理到信用社管理……

Pager艾达pter 刷新实验

1、更新数据源中的某项

更新数据测试

对应代码:

private void refresh() {
    mDataList.set(0, "更新数据源测试");
    mPagerAdapter.notifyDataSetChanged();
}

题材讲述:在示范动画中可以见到,更新数据源之后视图并不曾马上刷新,多滑行四遍重复重临更新的
Item 时才履新(那里先看难题,上边会细说)。

2、往数据源中添加数据

加上数据测试

对应代码:

private void add() {
    mDataList.add("这是新添加的Item");
    mPagerAdapter.notifyDataSetChanged();
}

题材讲述:没什么难点,数据源添加数据后文告 PagerAdapter
刷新,ViewPager 中就多了一个 Item。

3、从数据源中删除数据

剔除数据测试

private void delete() {
    mDataList.remove(0);
    mPagerAdapter.notifyDataSetChanged();
}

题材讲述:以此难点就较多了,首先,倘即使去除当前
Item,那么会合到没有其他反馈;其次,若是除去的不是时下
Item,会发觉现身了数码错乱,并且前边有 Item
滑不过去,不过按住未来滑的时候可以见到前边的 Item。

4、将数据源清空

清空数据

private void clean() {
    mDataList.clear();
    mPagerAdapter.notifyDataSetChanged();
}

标题讲述:从地点的动图可以看看,清空数据源之后,会残留一个 Item。

说明:先不要计较上边所写的 Pager艾达pter
是或不是有标题,那里只是想引出难点来,上边会指向
PagerAdapter、FragmentPagerAdapter 以及 FragmentStatePagerAdapter
来分析难点由来和交由解决方案。

3、《活法》

【书评】

稻盛和夫先生的治本文学格外例外,平常善于用简单的句子揭穿管理的长远含义,并且他越发器重“人”的管制。

在本书中,他指出了一个有趣的公式:“人生✖️工作的结果=思维情势✖️热情✖️能力”。

能力是大家日常平日生活和行事中讲述的工作能力、智商等目的。其中“思维方法”是意义很广的汇总目的,包罗一个人的天性、世界观、看东西的角度、价值观等,可以知道为大家一般所说的“软实力”。

咱俩发现众多的成功人士,并不一定是在智慧方面有足够杰出的显现,与此同时对于大家一大半人来说,智商和平凡处总管务的能力并不会有太大的界别。雾满拦江曾写过一篇作品,谈到智商并非一步一趋的,通过祥和的行事,或用力或懒惰,智商也会有增高或者下跌的浮动。

在自查自纠工作的古道热肠和思考格局那些软实力上,每个人方可透过学习、实践积累去提高的。思辨能力、多角度思考能力、审美能力、表明能力,甚至是相对而言工作的态度、对待旁人的善心……等等软实力,成为了竞争中的大旨元素。

另一种思路

不过,我在档次中实际利用的时候(Fragment
相比较复杂,里面有网络任务等)出现了 IllegalStateException,暴发在
”fragmentTransaction.remove(f);“
时。当时找了有的稿子没有解决该难点,考虑到品种中的 Fragment
里面逻辑过多,就换思路,没有在那一个方面继续探索了。

若是,你也是这样使用 FragmentStatePagerAdapter 来动态改变 ViewPager 中
Fragment,并且在 remove Fragment 时碰着了
IllegalStateException。那么,你能够考虑选用下边的不二法门,先看代码(FSPagerAdapter
.java):

public class FSPagerAdapter extends FragmentStatePagerAdapter {

    private ArrayList<Fragment> mFragmentList;

    public FSPagerAdapter(FragmentManager fm, List<Integer> types) {
        super(fm);
        updateData(types);
    }

    public void updateData(List<Integer> dataList) {
        ArrayList<Fragment> fragments = new ArrayList<>();
        for (int i = 0, size = dataList.size(); i < size; i++) {
            Log.e("FPagerAdapter1", dataList.get(i).toString());
            fragments.add(FragmentTest.instance(dataList.get(i)));
        }
        setFragmentList(fragments);
    }

    private void setFragmentList(ArrayList<Fragment> fragmentList) {
        if(this.mFragmentList != null){
            mFragmentList.clear();
        }
        this.mFragmentList = fragmentList;
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return this.mFragmentList.size();
    }

    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }
}

对应的测试 Activity 见 FSPagerAdapterActivity.java

地点的代码挺不难,稍微解释一下完成思路:
1、缓存所有的 Fragment
动用一个 List 将数据源对应的 Fragment 都缓存起来

2、更新数据源,刷新 Fragment
当有数据源更新的时候,从 List 中取出相应的 Fragment,然后刷新 Adapter

3、删除数据时,删除 List 中对应的 Fragment
当数码源中删除某项时,将 List 中对应的 Fragment 也删除,然后刷新 Adapter

种种人不管看书多少、职位高低,都或多或少的受限于自己的学识结构和商量方法,在待遇事物的时候都会习惯从自己的无理出发。

二、PagerAdapter

从地点的试行可以寓目 ViewPager 不一样于 ListView,固然单单的调用
ViewPager.getAdapter().notifyDataSetChanged() 方法(即 PagerAdapter 的
notifyDataSetChanged()方法)页面并从未刷新。

PagerAdapter 用于 ViewPager 的 Item 为一般
View的意况,那一个相对简单,所以首先介绍。

深信不疑广运城室都搜过类似的难题 —— “PagerAdapter 的 notifyDataSetChanged()
不刷新?”。有的说那是 bug,有的则以为 谷歌是专程这样设计的,个人倾向后一种观点(我觉着那是 Google 为了 ViewPager
质量考虑而规划的,毕竟 ViewPager
要求体现“很多的”视图,而且要幸免用户滑动时认为卡顿)。

2、《麦肯锡工作法》

【书评】

有两位书友分享了麦肯锡种类的书本,《麦肯锡工作法》和《麦肯锡-难题分析与缓解技术》。

麦肯锡那几个体系的书籍,提供了大气、实用的管住分析工具。管理者日常要面对困境、解决难题,而解决难题要从通晓一个题材的九华山真面目入手。

早已有一个麦肯锡咨询诊断的大方表嫂说:很多境内商店的问讯管理是想当然,咨询管理最重点的是把脉,发现了热点在哪儿才能因材施教,而不是疾病都尚未钻探透彻,就盲目标始发上马一多元培训项目。

麦肯锡提供了一文山会海的沉思方法和管理工具,辅助管理者培育发现难题的机警思维,和带着“解决难题”的笔触去分析宏观和微观的场合,指出解决方案。

两位书友感觉阅读麦肯锡的书本对于不是做管理咨询的人的话略感吃力。但两位书友都建议了“走出舒适区”阅读的视角。大家阅读是以兴趣开首,缺少兴趣很难百折不回下去。兴趣和出彩的文字技巧、翻译技巧是促使大家愿意继续阅读下去的维持。

在达到一定的“量”,而从量变走向质变将来,可以尝试去读那多少个不在舒适区以内的图书,也就是对我们而言有挑衅的书籍,踏入全新的领域,可以更快的拓展大家的知识面,同时作育更深切的开卷思维。

最简方案的优化

那里提供一个思路,毕竟场景太多,相信大家了解了思路要兑现就很不难了,闲话不多说。

思路:在 instantiateItem() 方法中给每个 View 添加 tag(使用 setTag()
方法),然后在 getItemPosition() 方法中通过 View.getTag()
来判断是或不是是须要刷新的页面,是就赶回 POSITION_NONE,否就再次来到POSITION_UNCHANGED。
(参考自:ViewPager刷新单个页面的法子

注意:此间有几许要专注的是,当清空数据源的时候须要再次回到POSITION_NONE,可用如下代码:

if (mDataList != null && mDataList.size()==0) {
    return POSITION_NONE;
}

至于 PagerAdapter 的牵线就到此处了,纵然 FragmentPagerAdapter 与
FragmentStatePagerAdapter 都是持续自
PagerAdapter。不过,那七个是特地为以 Fragment 为 Item 的 ViewPager
所准备的,所以有其特殊性。且看下边的介绍。

官方介绍

PageAdapter 类

PageAdapter 继承自
Object,继承结构参考意义不大,那老实看文档。文档上没有提供示范代码,只是说了下要自定义
PageAdapter 需求贯彻下边三个章程:

  • instantiateItem(ViewGroup container, int
    position):
    该办法的意义是创建指定地点的页面视图。适配器有义务增添即将创立的
    View 视图到此处给定的 container 中,那是为着确保在
    finishUpdate(viewGroup) 重返时 this is be done!
    重返值:重临一个象征新增视图页面的
    Object(Key),那里没要求非要再次来到视图本身,也可以这几个页面的此外容器。其实自己的了解是足以代表当前页面的任意值,只要你能够与你增添的
    View 一一对应即可,比如 position 变量也得以做为 Key
  • destroyItem(ViewGroup container, int position, Object
    object):
    该方式的效率是移除一个加以地点的页面。适配器有职责从容器中删去那个视图,那是为了保险在
    finishUpdate(viewGroup) 重临时视图可以被移除
  • getCount():回来当前有效视图的多少
  • isViewFromObject(View view, Object object):该函数用来判定
    instantiateItem() 函数所重返来的 Key
    与一个页面视图是还是不是是代表的同一个视图(即它俩是还是不是是对应的,对应的象征同一个
    View)
    再次回到值:借使对应的是同一个View,重回 true,否则再次回到 false

地点对 PageAdapter 的多少个抽象方法做了大致表明,下边看看如何接纳

提议难点

在行使 ListView 的时候,大家一再习惯了翻新 Adapter 的数据源,然后调用
Adapter 的 notifyDataSetChanged() 方法来刷新列表(有没多少 MVC
的感觉)。

Pager艾达pter 也有 notifyDataSetChanged()
方法,那我们根据那么些流程来试试,看有没有如何难点。(ListView
的以身作则就不在那里演示了,感兴趣的可以团结去尝试,极度不难)

那就是说我的题材是:“ViewPager 的 PagerAdapter
在数据源更新后,能不能自行刷新视图?

带着难点,大家做一些试行,下边实验的思绪是:修改数据源,然后布告PagerAdapter 更新,查看视图的变通。

ViewPager 刷新分析

先来了然下 ViewPager 的刷新进度:
1、刷新的发轫
ViewPager 的基础代谢是从调用其 PagerAdapter 的 notifyDataSetChanged()
方法开首的,那先看看该办法的源码(在源码面前一切无所遁形…):

/**
 * This method should be called by the application if the data backing this adapter has changed
 * and associated views should update.
 */
public void notifyDataSetChanged() {
    synchronized (this) {
        if (mViewPagerObserver != null) {
            mViewPagerObserver.onChanged();
        }
    }
    mObservable.notifyChanged();
}

2、DataSetObservable 的 notifyChanged()
上面的措施中冒出了多个重大的成员变量:

private final DataSetObservable mObservable = new DataSetObservable();
private DataSetObserver mViewPagerObserver;

观望者形式,有没有?先不着急分析那几个是或不是观望者情势,来探视
mObservable.notifyChanged() 做了些什么工作:

/**
 * Invokes {@link DataSetObserver#onChanged} on each observer.
 * Called when the contents of the data set have changed.  The recipient
 * will obtain the new contents the next time it queries the data set.
 */
public void notifyChanged() {
    synchronized(mObservers) {
        // since onChanged() is implemented by the app, it could do anything, including
        // removing itself from {@link mObservers} - and that could cause problems if
        // an iterator is used on the ArrayList {@link mObservers}.
        // to avoid such problems, just march thru the list in the reverse order.
        for (int i = mObservers.size() - 1; i >= 0; i--) {
            mObservers.get(i).onChanged(); 
        }
    }
}

notifyChanged() 方法中是很典型的观望者形式中遍历所有的 Observer,文告变化发生了的代码。代码很粗略,那根本是以此 mObservers 包蕴怎样 Observer
呢?

3、DataSetObserver
直接从 mObservers 点进去你会意识那么些:

protected final ArrayList<T> mObservers = new ArrayList<T>();

-_-‘,那是个泛型,坑了!还好 DataSetObservable 的 notifyChanged()
的诠释中写了那个 Observer 是 DataSetObserver。那去看看 DataSetObserver:

public abstract class DataSetObserver {
    /**
     * This method is called when the entire data set has changed,
     * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
     */
    public void onChanged() {
        // Do nothing
    }

    /**
     * This method is called when the entire data becomes invalid,
     * most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a
     * {@link Cursor}.
     */
    public void onInvalidated() {
        // Do nothing
    }
}

一个抽象类,里面多少个空方法,这几个好办,找他的子类(AndroidStudio 大校光标放到类名上,按 F4):

DataSetObserver继承结构

好不简单找到你了,就是用红线框出来的那条,双击,定位过去。

4、PagerObserver 内部类
PagerObserver 是 ViewPager 中的一个中间类,完毕也很不难,就是调用了
ViewPager 中的 dataSetChanged() 方法,真正的要紧来了。

private class PagerObserver extends DataSetObserver {
    @Override
    public void onChanged() {
        dataSetChanged();
    }
    @Override
    public void onInvalidated() {
        dataSetChanged();
    }
}

5、ViewPager 的 dataSetChanged()
其一办法的贯彻较长,里面的逻辑看上去挺复杂的,那里就不显得全部的源码了,列下关键点:

...
for (int i = 0; i < mItems.size(); i++) {
    final ItemInfo ii = mItems.get(i);
    final int newPos = mAdapter.getItemPosition(ii.object);

    if (newPos == PagerAdapter.POSITION_UNCHANGED) {
        continue;
    }

    if (newPos == PagerAdapter.POSITION_NONE) {
        ...
        continue;
    }
    ...
}
...

地点截取的代码中 for 循环之中有多个 continue
语句,那也许是比较重大的代码,幸好不用大家继续深入了,官方给出了诠释:

Called when the host view is attempting to determine if an item’s
position has changed. Returns POSITION_UNCHANGED if the position of the
given item has not changed or POSITION_NONE if the item is no longer
present in the adapter.The default implementation assumes that items
will never change position and always returns POSITION_UNCHANGED.

粗粗的意思是:
假定 Item 的地点如若没有爆发变化,则赶回 POSITION_UNCHANGED。如若回去了
POSITION_NONE,表示该义务的 Item 已经不设有了。默许的已毕是若是 Item
的职位永远不会暴发变化,而回到
POSITION_UNCHANGED。(参考自:追溯源码解决android疑难有关难点1-Viewpager之notifyDataSetChanged无刷新

下边在源码里面跟了一大圈是或不是依然感觉并未明朗,因为还有一个很重大的类
—— PagerAdapter 没有介绍,再给点耐心,继续。

6、PagerAdapter 的做事流程
其实就是 PagerAdapter 中艺术的举办各个,来探视
Leo8573
的分析(个人感觉基本说成功了,所以一向拷过来了):

PagerAdapter 作为 ViewPager 的适配器,无论 ViewPager
有稍许页,PagerAdapter 在开始化时也只开端化起初的2个
View,即调用2次instantiateItem 格局。而接下去每当 ViewPager
滑动时,PagerAdapter 都会调用 destroyItem
方法将相差该页2个涨幅以上的充裕 View 销毁,以此保险 PagerAdapter
最多只管辖3个 View,且当前 View 是3个中的中间一个,若是当前 View
缺少两边的 View,那么就 instantiateItem,如里有超常2个增幅的就
destroyItem。

简单易行图示:

                 *
   ------+---+---+---+------
     ... 0 | 1 | 2 | 3 | 4 ...
   ------+---+---+---+------

眼前 View 为2号 View,所以 PagerAdapter 管辖1、2、3多少个View,接下去向左滑动–>

                 *
   ------+---+---+---+------
     ... 1 | 2 | 3 | 4 | 5 ...
   ------+---+---+---+------

滑动后,当前 View 变为3号 View,PagerAdapter 会 destroyItem
0号View,instantiateItem 5号 View,所以 PagerAdapter 管辖2、3、4三个
View。(参考自:有关ViewPager的多寡更新难点统计

统计一下: Viewpager 的刷新进程是这样的,在每一次调用 PagerAdapter 的
notifyDataSetChanged() 方法时,都会激活 getItemPosition(Object object)
方法,该方法会遍历 ViewPager 的具备 Item(由缓存的 Item
数量控制,默许为当前页和其左右加起来共3页,这么些能够自行设定,可是起码会缓存2页),为每个
Item 重回一个状态值(POSITION_NONE/POSITION_UNCHANGED),如果是
POSITION_NONE,那么该 Item 会被 destroyItem(ViewGroup container, int
position, Object object) 方法 remove 掉,然后再次加载,倘若是
POSITION_UNCHANGED,就不会再次加载,默认是
POSITION_UNCHANGED,所以假设不重写 getItemPosition(Object
object),修改重回值,就不可以看出 notifyDataSetChanged() 的刷新功用。

PagerAdapter简介

ListView 大家应该都很熟识吧!ListView 一般都必要一个 Adapter
来填充数据,如 ArrayAdapter、Simple艾达pter。PagerAdapter 就是 ViewPager
的 Adapter,与 ListView 的 Adapter 效能一样。

ViewPager->PageAdapter == ListView->BaseAdapter

先看下官方介绍

最简便易行的化解方案

那就是直接一刀切:重写 PagerAdapter 的 getItemPosition(Object object)
方法,将重回值固定为 POSITION_NONE。

先看看效果:

![最简便解决方案示例](http://upload-images.jianshu.io/upload\_images/1233754-0071612440ec3200.gif?imageMogr2/auto-orient/strip
”最简单易行解决方案示例“)

上代码(PagerAdapterActivity.java):

@Override
public int getItemPosition(Object object) {
    // 最简单解决 notifyDataSetChanged() 页面不刷新问题的方法
    return POSITION_NONE;
}

该方案的老毛病:有个很明显的短处,那就是会刷新所有的
Item,那将导致系统资源的荒废,所以这种方法不切合数据量较大的场合。

注意:
那种格局还有一个索要注意的地点,就是重写 destoryItem() 方法:

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    // 把 Object 强转为 View,然后将 view 从 ViewGroup 中清除
    container.removeView((View) object);
}

PagerAdapter 刷新的难题

简介

FragmentStatePagerAdapter
与 FragmentPagerAdapter 类似,那三个类都持续自 PagerAdapter。可是,和
FragmentPagerAdapter 差距等的是,FragmentStatePager艾达pter
只保留当前页面,当页面离开视线后,就会被破除,释放其资源;而在页面必要展现时,生成新的页面(那和
ListView
的兑现均等)。这种形式的好处就是当所有大批量的页面时,不必在内存中占有大批量的内存。(参考自:FragmentPagerAdapter与FragmentStatePagerAdapter区别

FragmentStatePagerAdapter 的兑现与 FragmentPager艾达pter
有很大分裂,假诺照搬上述 FragmentPagerAdapter
刷新数据的格局,你会发现并未什么样难题(可以运用 FPagerAdapter11.java
测试)。

不难易行利用

mContentVP.setAdapter(new PagerAdapter() {
    @Override
    public int getCount() {
        return dataList.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = View.inflate(SimpleDemoActivity.this, R.layout.item_vp_demopageradapter, null);
        TextView pageNumTV = (TextView) view.findViewById(R.id.tv_pagenum);
        pageNumTV.setText("DIY-PageNum-" + dataList.get(position));
        container.addView(view);
        return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }

});

可以看到落成 PagerAdapter 与 BaseAdapter 很相近,只是 PagerAdapter 的
isViewFromObject() 与 instantiateItem() 方法须求可以明白下。那里为了简化
PagerAdapter 的运用,我做了个简易的包装:

public abstract class APagerAdapter<T> extends PagerAdapter {

    protected LayoutInflater mInflater;
    protected List<T> mDataList;
    private SparseArray<View> mViewSparseArray;

    public APagerAdapter(Context context, List<T> dataList) {
        mInflater = LayoutInflater.from(context);
        mDataList = dataList;
        mViewSparseArray = new SparseArray<View>(dataList.size());
    }

    @Override
    public int getCount() {
        if (mDataList == null) return 0;
        return mDataList.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = mViewSparseArray.get(position);
        if (view == null) {
            view = getView(position);
            mViewSparseArray.put(position, view);
        }
        container.addView(view);
        return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(mViewSparseArray.get(position));
    }

    public abstract View getView(int position);

}

APagerAdapter 类模仿 ListView 的 BaseAdapter,抽象出一个 getView()
方法,在其中采取 SparesArray 缓存所有呈现过的
View。这样使用就很不难了,继承 APagerAdapter,完成 getView()
方法即可(能够参照:DemoPagerAdapter.java)。

品类地址

GitHub
民用博客

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注