重新加载时刷新片段
Posted
技术标签:
【中文标题】重新加载时刷新片段【英文标题】:Refresh Fragment at reload 【发布时间】:2014-01-09 05:45:06 【问题描述】:在一个 android 应用程序中,我将数据从 Db 加载到 Fragment
内的 TableView
中。但是当我重新加载Fragment
时,它会显示以前的数据。我可以用当前数据而不是以前的数据重新填充Fragment
吗?
【问题讨论】:
请给我们一些代码。你在哪里加载数据,你从哪里开始你的片段,你在哪里存储你的值? 这应该可以解决您描述的问题:***.com/questions/6503189/… 请提供更多信息-code sn-p 尝试使用滑动刷新到您的应用程序看到这个***.com/questions/41469040/fragment-refresh/… 【参考方案1】:我想你想在数据库更新时刷新片段内容
如果是这样,分离片段并重新附加它
// Reload current fragment
Fragment frg = null;
frg = getSupportFragmentManager().findFragmentByTag("Your_Fragment_TAG");
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();
Your_Fragment_TAG 是您在创建片段时为其命名的名称
此代码用于支持库。
如果您不支持旧设备,只需使用 getFragmentManager 而不是 getSupportFragmentManager
[编辑]
此方法要求 Fragment 有标签。 如果你没有,那么@Hammer的方法就是你需要的。
【讨论】:
这会产生以下错误 - java.lang.RuntimeException: 将结果 ResultInfowho=null, request=2, result=3, data=null 传递给活动 xont.virtusel.v4.controller 失败/xont.virtusel.v4.controller.sale.InvocieBrandActivity:java.lang.IllegalStateException:onSaveInstanceState 后无法执行此操作 @Elizabeth 确保您的 Fragment 已正确设置标签 @Rotwang 感谢您的回复,我只是走捷径而不是编写长代码,但这有助于铺平道路:) 此解决方案在新版本的 support-v4-library (25.1.0) 中不再有效。此处说明:***.com/questions/41270858/… 警告:这个技巧只有在你使用 Support Fragments 时才对 Oreo 有效!【参考方案2】:这将刷新当前片段:
FragmentTransaction ft = getFragmentManager().beginTransaction();
if (Build.VERSION.SDK_INT >= 26)
ft.setReorderingAllowed(false);
ft.detach(this).attach(this).commit();
【讨论】:
这段代码放在哪里?内部活动还是片段本身? 你把它放在需要刷新的fragment里面。 @SagarChavada 你把代码放在哪里了?您必须将其放入一次性事件中,例如刷新数据时。 递归,递归,没完没了的调用 在片段的onResume中使用这个creates会造成循环,如何避免呢?【参考方案3】:如果你没有片段标签,下面的代码很适合我。
Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
if (currentFragment instanceof "NAME OF YOUR FRAGMENT CLASS")
FragmentTransaction fragTransaction = (getActivity()).getFragmentManager().beginTransaction();
fragTransaction.detach(currentFragment);
fragTransaction.attach(currentFragment);
fragTransaction.commit();
【讨论】:
片段 ID 是什么,我没有在任何地方声明片段 ID。如何以及在哪里申报? 我的活动中似乎无法使用getActivity()
。我应该使用Activity.this...
吗?
@NarendraJi 它的 FrameLayout id 仅用于将片段放入容器中。
请移除多余的支架。这给我带来了很多麻烦。【参考方案4】:
刷新片段接受的答案不适用于牛轧糖及以上版本。要使其适用于所有操作系统,您可以执行以下操作。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
fragmentManager.beginTransaction().detach(this).commitNow();
fragmentManager.beginTransaction().attach(this).commitNow();
else
fragmentManager.beginTransaction().detach(this).attach(this).commit();
【讨论】:
使用两个事务对我有用。谢谢你的想法。 更新我的 gradle 构建文件后,片段将不再重新加载。你的回答解决了这个问题。谢谢。 谢谢一百万【参考方案5】:您可以在对用户可见时刷新片段, 只需将此代码添加到您的片段中,这将在片段可见时刷新您的片段。
@Override
public void setUserVisibleHint(boolean isVisibleToUser)
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser)
// Refresh your fragment here
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
Log.i("IsRefresh", "Yes");
【讨论】:
太慢了,需要 3 秒才能重新加载 这似乎与 viewpager 适配器配合得很好 setUserVisibleHint 已弃用【参考方案6】:当 Fragment 附加到 Activity 时,您无法重新加载该 Fragment,您会收到“Fragment Already Added
”异常。
因此,必须首先将片段与其活动分离,然后再附加。一切都可以在一行中使用 fluent api 完成:
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
更新: 这是为了合并对 API 26 及更高版本所做的更改:
FragmentTransaction transaction = mActivity.getFragmentManager()
.beginTransaction();
if (Build.VERSION.SDK_INT >= 26)
transaction.setReorderingAllowed(false);
transaction.detach(this).attach
(this).commit();
有关更新的更多说明,请参阅https://***.com/a/51327440/4514796
【讨论】:
请提供您的答案并提供清晰的描述。不要写代码,把你分享的代码解释一下,让别人也能理解,对你有帮助。我请求您阅读常见问题解答部分,以便有效地使用 Stack Overflow。【参考方案7】: MyFragment fragment = (MyFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
getSupportFragmentManager().beginTransaction().detach(fragment).attach(fragment).commit();
这只有在你使用FragmentManager
来初始化片段时才有效。如果您将它作为 XML 中的 <fragment ... />
,它不会再次调用 onCreateView
。浪费了我 30 分钟来解决这个问题。
【讨论】:
【参考方案8】:如果你使用的是 NavController,试试这个(kotlin):
val navController = findNavController()
navController.run
popBackStack()
navigate(R.id.yourFragment)
【讨论】:
你能解释一下为什么这应该有效吗? 对不起,忘记补码了。【参考方案9】:在这里我做了什么,它对我有用或者这里的上下文是我在 kotlin 语言中使用和工作的代码我认为你可以在 java 类中使用相同的代码
override fun setUserVisibleHint(isVisibleToUser: Boolean)
super.setUserVisibleHint(isVisibleToUser)
val context = requireActivity()
if (auth.currentUser != null)
if (isVisibleToUser)
context.supportFragmentManager.beginTransaction().detach(this).attach(this).commit()
【讨论】:
【参考方案10】:getActivity().getSupportFragmentManager().beginTransaction().replace(GeneralInfo.this.getId(), new GeneralInfo()).commit();
GeneralInfo
这是我的片段类GeneralInfo.java
我把它作为一个方法放在了片段类中:
public void Reload()
getActivity().getSupportFragmentManager().beginTransaction().replace(LogActivity.this.getId(), new LogActivity()).commit();
【讨论】:
【参考方案11】:如果您使用的是导航组件
您可以使用navigate(this_fragment_id)
导航到此片段,但在新实例中。此外,您还必须在删除实际片段之前弹出 backstack。
科特林
val navController: NavController =
requireActivity().findNavController(R.id.navHostFragment)
navController.run
popBackStack()
navigate(R.id.this_fragment_id)
Java
NavController navController =
requireActivity().findNavController(R.id.navHostFragment);
navController.popBackStack();
navController.navigate(R.id.this_fragment_id);
【讨论】:
【参考方案12】:使用ContentProvider
并使用“CursorLoader”加载数据。使用这种架构,您的数据将在数据库更改时自动重新加载。将third-party frameworks 用于您的ContentProvider
- 您真的不想自己实现它...
【讨论】:
【参考方案13】:我遇到了同样的问题,但以上都不适用于我。要么有一个 backstack 问题(加载后当用户按下它会再次进入相同的片段)或者它没有调用 onCreaetView
我终于做到了:
public void transactFragment(Fragment fragment, boolean reload)
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
if (reload)
getSupportFragmentManager().popBackStack();
transaction.replace(R.id.main_activity_frame_layout, fragment);
transaction.addToBackStack(null);
transaction.commit();
好点是你也不需要片段的标签或 id。 如果你想重新加载
【讨论】:
【参考方案14】:在片段活动和持有片段的活动上使用 onResume 方法。
【讨论】:
【参考方案15】:以 TabLayout 为例:只需实现 OnTabSelectedListener。要重新加载页面,您可以使用实现 SwipeRefreshLayout.OnRefreshListener 即public class YourFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener
onRefresh() 方法将是来自接口的@Override,即:
@Override
public void onRefresh()
loadData();
这是布局:
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_
android:layout_
android:background="@color/colorPrimaryLighter"
app:tabGravity="fill"
app:tabIndicatorColor="@color/white"
app:tabMode="fixed"
app:tabSelectedTextColor="@color/colorTextPrimary"
app:tabTextColor="@color/colorTextDisable" />
活动中的代码
TabLayout tabLayout = (TabLayout) findViewById(R.id.tablayout); tabLayout.setupWithViewPager(viewPager);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
@Override
public void onTabSelected(TabLayout.Tab tab)
if (tab.getPosition() == 0)
yourFragment1.onRefresh();
else if (tab.getPosition() == 1)
yourFragment2.onRefresh();
@Override
public void onTabUnselected(TabLayout.Tab tab)
@Override
public void onTabReselected(TabLayout.Tab tab)
);
【讨论】:
【参考方案16】:// Reload current fragment
Fragment frag = new Order();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.fragment_home, frag).commit();
【讨论】:
这个问题是近七年前回答的,有两个答案,每个答案都超过 100 票,另外还有 13 个答案。有几个使用类似的整体方法——尽管没有一个专门使用R.id.fragment_home
。你的方法有什么好处?为什么有人要在一个高度赞成的答案中使用它?可以为旧问题添加新答案,但请编辑您的答案以提供为什么您的答案对该主题有贡献的摘要。
我也尝试了上述两种方法,获得了 100 多票,但都没有解决我的问题,因为第一种方法是使用 findFragmentByTag,但在我的情况下,它返回一个空值,而第二个答案“ ft.detach(this)” 我无法使用“this”,因为它总是显示红线,因为我正在使用位置监听器,而不是给我一个片段,它返回一个位置监听器,所以我能够做到的唯一方法重新加载我的片段是答案中的方法。【参考方案17】:
这些答案都不适合我,所以如果有人对此仍有问题,我不妨发布我的解决方案。此解决方案仅在您使用导航组件时才有效。
转到您的导航图并找到您要刷新的片段。从该片段到自身创建一个动作。现在您可以像这样在该片段中调用该操作。
private void refreshFragment()
// This method refreshes the fragment
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_self);
【讨论】:
我如何在self Fragment中获得FirstFragment.this
?
@Freax FirstFragment 是我从中调用此方法的片段。将其更改为您的片段名称。【参考方案18】:
Below code reloads the current fragment onClick of button from Parent Activity.
layoutNews.setOnClickListener(v ->
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, fragNews);
ft.detach(fragNews);
ft.attach(fragNews);
ft.commit();
);
【讨论】:
【参考方案19】:最简单的方法
创建一个包含 viewpager.setAdapter 的公共静态方法
使适配器和 viewpager 成为静态
public static void refreshFragments()
viewPager.setAdapter(adapter);
在任何地方、任何活动、任何片段中调用。
MainActivity.refreshFragments();
【讨论】:
【参考方案20】:protected void onResume()
super.onResume();
viewPagerAdapter.notifyDataSetChanged();
一定要写 viewpagerAdapter.notifyDataSetChanged();在 MainActivity 的 onResume() 中。 祝你好运:)
【讨论】:
以上是关于重新加载时刷新片段的主要内容,如果未能解决你的问题,请参考以下文章
thymeleaf 片段渲染后重新加载 javascript