Android导航组件不断重新加载WebView

时间:2019-05-13 15:27:09

标签: java android kotlin webview android-architecture-navigation

今天,在WebView内使用Fragment的{​​{1}}遇到了问题。 在我的情况下,Android Navigation ComponentFragment1下有一个按钮。用户需要向下滚动才能单击它。单击它后,将打开一个新的目的地(WebView)。然后,当用户返回到Fragment2时,Fragment1被重新加载,并且视口再次滚动到顶部。

这很烦人。用户可能向下滚动了几分钟,并且总是在返回后将其扔到最顶端。我能以某种方式阻止它重新加载/滚动回到顶部吗?

示例代码可能就这么简单:

WebView

如果class Fragment1 : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) webView.loadData(getString(R.string.some_very_long_html), "text/html", "UTF-8") buttonBelowWebView.setOnClickListener { navigateToFragment2() } } } 包含视频,则加载可能最多需要5秒钟。这是糟糕的经历。

我尝试添加标志以仅加载一次,但是从WebView导航回来时WebView为空:

Fragment2

请注意,在现实生活中,我使用class Fragment1 : Fragment() { var loaded = false override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) if(!loaded) { webView.loadData(getString(R.string.some_very_long_html), "text/html", "UTF-8") loaded = true } } } 并观察来自rest api的数据,但是问题仍然存在。

此外,我提供的示例代码是用Kotlin编写的,但是如果有Java解决方案,那么也很感激。

从嵌套目标位置导航回来时是否可以不重新加载ViewModel并重置滚动位置?

5 个答案:

答案 0 :(得分:5)

这是片段以其基本形式(导航组件使用的形式)工作的方式

片段本身被保存,但是它们的视图被破坏了。

这是您所遇到的情况:

  • 片段1已创建
  • 已创建片段1视图(其中包含web视图)
  • 单击按钮
  • 片段1视图被破坏
  • 片段2已创建
  • 创建片段2视图
  • 返回点击
  • 重新创建片段1视图
  • 片段2视图被破坏
  • 片段2被摧毁

如果您不使用导航组件,则使用非骇客的方式很容易解决。
您可以在FragmentTransaction上简单地将.hide().add()结合使用,而不是.replace(),并且片段视图不会被破坏。

但是看到您在使用导航组件时,您自己并没有在处理碎片事务。

一种解决方法是在此处发布:
https://stackoverflow.com/a/55039009/2877453

保存片段及其变量后,您可以将视图另存为片段中的变量。
然后检查onCreateView,如果变量为null,则像往常一样将其膨胀,如果不为null,则返回保存的视图。

答案 1 :(得分:2)

在更改片段之前使用此代码:-

if (getVisibleFragment() instanceof Fragment1){
      // do nothing
}else{
      // replace fragment
}


    public Fragment getVisibleFragment(){
                FragmentManager fragmentManager = getSupportFragmentManager();
                List<Fragment> fragments = fragmentManager.getFragments();
                if(fragments != null){
                    for(Fragment fragment : fragments){
                        if(fragment != null && fragment.isVisible())
                            return fragment;
                    }
                }
                return null;
    }

答案 2 :(得分:2)

请更改为此

class Fragment1 : Fragment() {

 @Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    webView?.loadData(getString(R.string.some_very_long_html), "text/html", "UTF8")
   }

}

尝试

答案 3 :(得分:2)

嘿,当您第一次遇到片段或返回其方法onViewCreated时,总是会一遍又一遍地调用,如果您想不想重置,可以通过一个全局布尔检查来完成,因为该全局变量片段恢复后将不会更改

var shouldLoad = true

然后您想做什么

if(shouldLoad){
  //do your work

  //setting false to your boolean
  shouldLoad = false
}else{
  //if you need something else
}

答案 4 :(得分:2)

尝试一下-

这将在具有webview的片段中实现

 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    if (view == null) {
        // inflate your layout here
        return view = inflater.inflate(R.layout.community_home_layout, container, false);
     }else {
      return view;
  }