重新加载时刷新片段

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() 中。 祝你好运:)

【讨论】:

以上是关于重新加载时刷新片段的主要内容,如果未能解决你的问题,请参考以下文章

在片段中重新加载android视图

thymeleaf 片段渲染后重新加载 javascript

Thymeleaf - 如何交互和重新加载 Javascript?

更改选项卡时避免/防止片段刷新

片段在重新加载时崩溃

刷新标签片段和 viewpager