YouTube如何处理其标签片段的生命周期?当我点击选项卡时它会启动并继续加载数据,即使我切换了该选项卡。当我再次重新选择该选项卡时,它不会重新加载它的视图和数据。我认为有一些布尔变量,比如didFeedLoad,然后在onCreate中设置为true?但在我看来,这不是优雅和良好的解决方案。你觉得怎么样?
在我的应用中,而不是ViewPager和TabLayout,我有BottomNavigationView,但我想像YouTube Android应用程序一样处理生命周期
以下是导航代码:
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame_layout, new OneFragment());
fragmentTransaction.commit();
BottomNavigationView bottomNavigationView =
(BottomNavigationView) findViewById(R.id.bottom_navigation_view);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
Fragment fragment = null;
switch (item.getItemId()) {
case R.id.action_one:
fragment = new OneFragment();
break;
case R.id.action_two:
fragment = new TwoFragment();
break;
case R.id.action_three:
fragment = new ThreeFragment();
break;
case R.id.action_four:
fragment = new FourFragment();
break;
case R.id.action_five:
fragment = new FiveFragment();
break;
}
if (fragment != null) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame_layout, fragment);
fragmentTransaction.commit();
}
return true;
}
});
答案 0 :(得分:2)
您正在寻找的是ViewPager .setOffscreenPageLimit(int limit)
来自Android Support Library (v4) Documentation:
设置应保留到的任意一侧的页数 处于空闲状态的视图层次结构中的当前页面。页面超出此范围 在需要时,将从适配器重新创建限制。
默认值:1
如果您有 4个标签,并且您希望它们全部保持闲置状态并且永远不会被销毁。重新创建(如YouTube应用),您可能需要将限制设置为 3 。
将YouTube应用作为一个案例场景(4个标签),我相信它的ViewPager或多或少地以这种方式定义:
ViewPager mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(3);
修改强> 关于BottomNavigationView - 只要你将它链接到ViewPager,无论你使用这个还是TabLayout都没关系。但经过二读,我知道你根本不使用ViewPager,所以我想知道你使用了什么,这样我的帮助才能完成
(此外,为什么不使用ViewPager?它看起来像是完美的解决方案)
答案 1 :(得分:0)
我怀疑YouTube标签片段是正常的片段。切换标签时,它们可能(并且可能)被杀死。它们只是在后台加载数据(在主活动/不同的线程上),然后在本地缓存/存储该数据,因此当您再次切换到相同的选项卡时,使用存储/缓存的数据可以非常快速地重新绘制数据。
答案 2 :(得分:0)
每次单击底部导航视图选项卡时,您正在加载片段的新实例。
要做的是,一旦创建了片段的单个实例,
然后,您只需要像这样使用支持片段管理器的隐藏和显示方法...
{ supportFragmentManager.beginTransaction().hide(currentFragment!!).show(prev_fragment).commit()
}
下面,我写了完整的实现。
class MainActivity : AppCompatActivity()
{
private lateinit var bottomNavigation:BottomNavigationView
private var currentTag:String="null"
private var currentFragment:Fragment?=null
private lateinit var homeFragment:Fragment
private lateinit var midFragment:Fragment
private lateinit var profileFragment:Fragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
}
private fun init() {
homeFragment= HomeFragment()
midFragment= MidFragment()
profileFragment= ProfileFragment()
bottomNavigation=findViewById(R.id.btm_nav)
bottomNavigation.setOnNavigationItemSelectedListener(object :BottomNavigationView.OnNavigationItemSelectedListener{
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.action_home->{
updateFragment(homeFragment,"home")
return true
}
R.id.action_mid->{
updateFragment(midFragment,"mid")
return true
}
R.id.action_profile->{
updateFragment(profileFragment,"profile")
return true
}
}
return false
}
})
updateFragment(homeFragment,"home")
}
fun updateFragment(fragment:Fragment, tag:String){
if (currentTag.equals(tag)){
return
}
var prev_fragment=supportFragmentManager.findFragmentByTag(tag)
// if fragment is not present in stack
if (prev_fragment==null){
if (currentFragment==null){
supportFragmentManager.beginTransaction().add(R.id.frag_container,fragment,tag).commit()
}else{
supportFragmentManager.beginTransaction().hide(currentFragment!!).add(R.id.frag_container,fragment,tag).commit()
}
}
// if fragment is already added
else{
supportFragmentManager.beginTransaction().hide(currentFragment!!).show(prev_fragment).commit()
}
currentFragment=fragment
currentTag=tag
}
如果您还想维护该片段的后堆栈,我已经设法借助堆栈来做到这一点。这是完整代码的GitHub链接。 link