Android 处理隐藏和显示的反压片段
我有一个活动,它承载三个Android 处理隐藏和显示的反压片段,android,android-fragments,Android,Android Fragments,我有一个活动,它承载三个片段,我可以使用底部导航视图在片段之间切换。我用来在片段之间切换的机制是使用显示和隐藏片段事务的功能,而不是替换碎片事务的功能。我这样做是因为我希望某些网络操作只执行一次,并且只对布局充气一次 使用此机制所面临的问题是,当我从任何片段启动另一个活动,然后点击后退按钮时,底部导航视图的selectedItem与显示的片段不匹配 虽然我能解决这个问题,但我觉得效率较低。程序是,每当我在切换片段时单击底部导航中的选项卡时,我都会给它一些预先指定的数字,并保存在一个静态变量(X)
片段
,我可以使用底部导航视图
在片段
之间切换。我用来在片段
之间切换的机制是使用显示
和隐藏片段事务
的功能,而不是替换
碎片事务的功能
。我这样做是因为我希望某些网络操作只执行一次,并且只对布局充气一次
使用此机制所面临的问题是,当我从任何片段
启动另一个活动
,然后点击后退按钮时,底部导航视图
的selectedItem与显示的片段
不匹配
虽然我能解决这个问题,但我觉得效率较低。程序是,每当我在切换片段时单击底部导航中的选项卡时,我都会给它一些预先指定的数字,并保存在一个静态变量(X
)中,每当我单击OnResume()中的后退按钮时
托管活动的方法我使用X
制作了一个开关盒块,在开始新活动之前知道哪个Fragment
可见,然后最后制作三个FragmentTransaction
,以显示和隐藏所需的Fragment
protected void onResume() {
super.onResume();
if(selectedId!=63){
switch(selectedId){
case 0:if(bottomNavigationView.getSelectedItemId()==R.id.navigation_home){handleHomeFragmentVisibility();}
break;
case 1:if(bottomNavigationView.getSelectedItemId()==R.id.navigation_dashboard)
{handleDashboardFragmentVisibility();}
break;
case 2:if(bottomNavigationView.getSelectedItemId()==R.id.navigation_notifications)
{handleNotificationFragmentVisibility();}
break;
}
}
我觉得使用三个片段事务
的成本很高,我正在寻找一些有效的方法。如果你知道的话,你能告诉我一个吗
public void handleHomeFragmentVisibility(){
FragmentManager fragmentManager= getSupportFragmentManager();
if (fragmentManager.findFragmentByTag("home") != null) {
//if the fragment exists, show it.
fragmentManager.beginTransaction().show(fragmentManager.findFragmentByTag("home")).commit();
} else {
//if the fragment does not exist, add it to fragment manager.
Log.e(TAG,"homeFragmentAdded");
fragmentManager.beginTransaction().add(R.id.container, new HomeFragment(), "home").commit();
}
if (fragmentManager.findFragmentByTag("dashboard") != null) {
//if the other fragment is visible, hide it.
fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag("dashboard")).commit();
}
if (fragmentManager.findFragmentByTag("requests") != null) {
//if the other fragment is visible, hide it.
fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag("requests")).commit();
}
}
public void handleDashboardFragmentVisibility(){
FragmentManager fragmentManager= getSupportFragmentManager();
if (fragmentManager.findFragmentByTag("dashboard") != null) {
//if the fragment exists, show it.
fragmentManager.beginTransaction().show(fragmentManager.findFragmentByTag("dashboard")).commit();
} else {
//if the fragment does not exist, add it to fragment manager.
fragmentManager.beginTransaction().add(R.id.container, new DashboardFragment(), "dashboard").commit();
}
if (fragmentManager.findFragmentByTag("home") != null) {
//if the other fragment is visible, hide it.
fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag("home")).commit();
}
if (fragmentManager.findFragmentByTag("requests") != null) {
//if the other fragment is visible, hide it.
fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag("requests")).commit();
}
}
public void handleNotificationFragmentVisibility(){
FragmentManager fragmentManager= getSupportFragmentManager();
if (fragmentManager.findFragmentByTag("requests") != null) {
//if the fragment exists, show it.
fragmentManager.beginTransaction().show(fragmentManager.findFragmentByTag("requests")).commit();
} else {
//if the fragment does not exist, add it to fragment manager.
fragmentManager.beginTransaction().add(R.id.container, new NotificationFragment(), "requests").commit();
}
if (fragmentManager.findFragmentByTag("home") != null) {
//if the other fragment is visible, hide it.
fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag("home")).commit();
}
if (fragmentManager.findFragmentByTag("dashboard") != null) {
//if the other fragment is visible, hide it.
fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag("dashboard")).commit();
}
}
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
FragmentManager fragmentManager = getSupportFragmentManager();
switch (item.getItemId()) {
case R.id.navigation_home:
selectedId=0;
handleHomeFragmentVisibility();
break;
case R.id.navigation_dashboard:
selectedId=1;
handleDashboardFragmentVisibility();
break;
case R.id.navigation_notifications:
selectedId=2;
handleNotificationFragmentVisibility();
break;
}
return true;
}
});
关于代码的第一个注意事项:避免使用样板文件!只编写一个方法而不是三个,并使用类型为handleFragmentVisibility(字符串显示、字符串hide1、字符串hide2、int容器)的签名
。如果要显示的片段为null
,请通过测试show
,将其实例化,如下所示:
Fragment newFragment = (show == "home") ? new HomeFragment() : (show == "dashboard") ? new DashboardFragment() : new NotificationFragment();
但是,您的任何片段都不应通过隐藏(请自己检查)而获得null
,因为您不会从活动中删除它们或用其他片段替换它们。除了使用show
和hide
之外,还可以使用attach
和detach
,这两组方法都保持状态。我没有看到效率问题,您确实需要调用三个FragmentTransaction
s。只能用较少的代码完成:
public void handleFragmentVisibility(String show, String hide1, String hide2){
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().show(fragmentManager.findFragmentByTag(show)).commit();
fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag(hide1)).commit();
fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag(hide2)).commit();
}
请注意,尽管此方法在隐藏或分离片段时保持片段的状态,但其他事件(如方向更改)仍然需要您在保存InstanceState(Bundle savedInstanceState)
中保存状态,您不清楚自己在问什么。我理解,在开始一项新活动后,您希望能够返回到旧活动并恢复状态。为此,您需要在活动包中保存一个变量,并在返回后将其恢复。例如,它可以是片段列表的索引。不需要调用多个FragmentTransaction
,并且在onResume()
代码中不调用任何事务。当一个switch语句就足够时,使用if-switch-if-cascade并不是特别有效,但也不太昂贵。@KalaBalik我使用三个事务,因为我需要显示一个片段并隐藏另外两个片段,否则两个或三个片段将显示为相互重叠,这是无意的。我在if
块inisde开关中调用的每个函数都有三个事务,每个事务都显示和隐藏所需的片段。使用setOnNavigationItemSelectedListener
将大大简化这一过程。您是否遇到性能缓慢的问题?您的操作方式没有问题。如果我是你,我会保持原样,我知道一个简单函数需要很多代码。