Android 保存 Fragment 引用及 getActivity() 为空问题(4)
- UID
- 1066743
|
Android 保存 Fragment 引用及 getActivity() 为空问题(4)
因此取到 Fragment 引用的方法也就找到了:
方法一
既然我们都知道 tag 的生成规则了, 找到 Fragment 那还不是 so easy.
还是以上面的 示例代码1 为例, 获取 fragment1 的引用, 这么做就可以了:
private void changeFragment1Text() {
String tag = "android:switcher:" + R.id.view_pager + ":" + 0;
Fragment1 fragment1 = (Fragment1) getSupportFragmentManager().findFragmentByTag(tag);
// 一定要做判空, 因为你要找的 Fragment 这时可能还没有加入 Activity 中.
if (fragment1 != null) {
fragment1.setText("Laziness is a programmer's feature.");
} else {
Log.e("lyux", "fragment not added yet.");
}
}
这种方法有两个缺点:
一是, tag 的规则依赖一个源码中的私有方法, 谷歌大大哪天不爽要改了这条规则, 我们的程序就会出错了.
二是, 对于另一个装载 Fragment 的 PagerAdapter, 即 FragmentStatePagerAdapter, 这个方法是不适用的.
FragmentStatePagerAdapter 是为了懒加载及页面回收的目的而编写的, 即不把每个 page 页的内容都保存在内存里. 因此它在创建了 Fragment 后, 没有给其附加 tag. 所以由它创建的 Fragment 无法用 FragmentManager.findFragmentByTag() 方法找到. 具体见其源码, 也不长.
方法二
还有一种思路, 是重载 FragmentPagerAdapter 类中的 instantiateItem() 方法, 得到 Fragment 引用. 依然以 示例代码1 为例, 将 SlidePagerAdapter 做如下改写即可:
public class TabChangeActivity extends AppCompatActivity {
private ViewPager mViewPager;
private Fragment1 mFragment1;
private Fragment2 mFragment2;
private Fragment3 mFragment3;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab_fragment_sample);
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mViewPager.setAdapter(new SlidePagerAdapter(getSupportFragmentManager()));
// 延迟5秒改变文字. 如果立刻执行, mFragment1 肯定是 null.
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (mFragment1 != null) {
mFragment1.setText("Every program must have a purpose. If not, it is deleted. -- The Matrix");
}
}
}, 5000);
}
private class SlidePagerAdapter extends FragmentPagerAdapter {
public SlidePagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
default:
return null; // unlikely to happen
}
}
@Override
public int getCount() {
return 3;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
switch (position) {
case 0:
mFragment1 = (Fragment1) fragment;
break;
case 1:
mFragment2 = (Fragment2) fragment;
break;
case 2:
mFragment3 = (Fragment3) fragment;
break;
}
return fragment;
}
}
}
因为 instantiateItem() 方法管理了 Fragment 的创建及重用, 因此无论其是新创建的, 还是被恢复的, 都可以正确取到引用.
注意: 不要在 FragmentStatePagerAdapter 场景中使用该方法. 因为我们保存了每一页的 Fragment 的引用, 就会阻止其被回收, 那 FragmentStatePagerAdapter 就白用了: 不就是为了可以回收页面才用它的嘛.
真要用的话就用 WeakReference<Fragment> 保存其弱引用.
但据说 4.0 后的 Android 虚拟机中弱引用等于没引用, 会很快被回收掉. (这句是听一位虚拟机大牛说的) |
|
|
|
|
|