【问题标题】:Refresh Fragment at reload重新加载时刷新片段
【发布时间】:2014-01-09 05:45:06
【问题描述】:

在一个 android 应用程序中,我将数据从 Db 加载到 Fragment 内的 TableView 中。但是当我重新加载Fragment 时,它会显示以前的数据。我可以用当前数据而不是以前的数据重新填充Fragment 吗?

【问题讨论】:

标签: android android-fragments


【解决方案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: 将结果 ResultInfo{who=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) 中不再有效。此处说明:stackoverflow.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://stackoverflow.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_width="match_parent"
                    android:layout_height="wrap_content"
                    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() 中。 祝你好运:)

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2015-11-16
                        • 2012-12-15
                        • 1970-01-01
                        • 2012-11-25
                        相关资源
                        最近更新 更多