navigateUp() 和 navigate(action_id) 没有按预期工作

navigateUp() and navigate(action_id) not working as expected

使用导航框架,我从 Homefragment 导航到 WhsSearchWebDB 并返回到 Homefragment

当通过 navController.navigate(R.id.action_whsSearchWebDB_to_nav_home)navController.navigateUp() 返回时,屏幕完全变白并且 toolbar 仅部分更新:片段的名称已正确设置,但导航按钮显示后退箭头而不是三栏主页图标。

当通过后退按钮返回时(navController.navigate(R.id.action_whsSearchWebDB_to_nav_home)navController.navigateUp() 评论,当然),一切正常。

我需要以编程方式返回,而不是通过用户单击后退按钮。我必须改变什么?

mobile_navigation.xml:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@id/nav_home">

<fragment
    android:id="@+id/nav_home"
    android:name="be.ema.golfclubdataconversion.ui.home.HomeFragment"
    android:label="@string/menu_home"
    tools:layout="@layout/fragment_home" >
    <action
        android:id="@+id/action_nav_home_to_whsSearchWebDB"
        app:destination="@id/whsSearchWebDB" />
</fragment>

<fragment
    android:id="@+id/nav_gallery"
    android:name="be.ema.golfclubdataconversion.ui.gallery.GalleryFragment"
    android:label="@string/menu_gallery"
    tools:layout="@layout/fragment_gallery" />

<fragment
    android:id="@+id/nav_slideshow"
    android:name="be.ema.golfclubdataconversion.ui.slideshow.SlideshowFragment"
    android:label="@string/menu_slideshow"
    tools:layout="@layout/fragment_slideshow" />

<fragment
    android:id="@+id/whsSearchWebDB"
    android:name="be.ema.golfclubdataconversion.ui.WhsSearchWebDB"
    android:label="WhsSearchWebDB"
    tools:layout="@layout/search_web_db">
    <action
        android:id="@+id/action_whsSearchWebDB_to_nav_home"
        app:destination="@id/nav_home" />
</fragment>

home_fragment代码:

public class HomeFragment extends Fragment {
public static View root = null;
private HomeViewModel homeViewModel;

public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_home, container, false);
}

@Override
public void onViewCreated(View root, Bundle savedInstanceState) {
//        super.onViewCreated(root, savedInstanceState);

//        homeViewModel = new ViewModelProvider(this).get(HomeViewModel.class);

    Button openUrlBtn = root.findViewById(R.id.openUrlBtn);
    openUrlBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            NavController navController = Navigation.findNavController(getActivity(), R.id.nav_host_fragment);
            navController.navigate(R.id.action_nav_home_to_whsSearchWebDB);
        }
    });
}
}

WhsSearchWebDB 代码:

public class WhsSearchWebDB extends Fragment {
public static Activity activity;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.search_web_db, container, false);
    return v;
}

@Override
public void onViewCreated(View root, Bundle savedInstanceState) {
    super.onViewCreated(root, savedInstanceState);
    activity = getActivity();

    String urlToBeOpened = "http://ncrdb.usga.org";

    WebView webView = (WebView) root.findViewById(R.id.webView1);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
    webView.setWebViewClient(new WebViewClient(){
        @Override
        public void onPageFinished(WebView view, String url)
        {
            /* This call inject JavaScript into the page which just finished loading. */
            webView.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
        }
    });
    webView.loadUrl(urlToBeOpened);
}

public static class MyJavaScriptInterface {
    @JavascriptInterface
    public void processHTML(String html) {
        NavController navController = Navigation.findNavController(activity, R.id.nav_host_fragment);

//            navController.navigate(R.id.action_whsSearchWebDB_to_nav_home);
//            if (!navController.navigateUp()) {
//                System.out.println("nooooooo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
//            }
    }
}
}

**** 编辑 **** 这是预期的屏幕(在转到 WhsSearchWebDB 片段之前拍摄的照片:

这是尝试返回后的错误结果:

whsSearchWebDB 片段中的导航操作正在创建一个新片段,而不是弹出回原始片段。

<fragment
    android:id="@+id/whsSearchWebDB"
    android:name="be.ema.golfclubdataconversion.ui.WhsSearchWebDB"
    android:label="WhsSearchWebDB"
    tools:layout="@layout/search_web_db">
    <action
        android:id="@+id/action_whsSearchWebDB_to_nav_home"
        // Change this
        app:destination="@id/nav_home"
        // To this to pop back
        app:popUpTo="@id/nav_home" />

我没有包括 popUpToInclusive。 PopUPToInclusive 需要设置为 true,popUpTo 属性将从返回堆栈中删除所有目的地,包括给定目的地。

  1. 打开导航图
  2. Select动作,你要
  3. 在属性窗格中,将 homeFragment 的 popUptToInclusive 设置为 Select popUpToInclusive 复选框为真。

有关详细信息,请查看导航代码实验室。 https://developer.android.com/codelabs/android-navigation#6

我终于发现 processHTML 方法在后台线程上执行,因此不允许操作 UI 小部件。我更喜欢 crash/error 而不是我在问题中报告的意外行为。

我已通过实施 ViewModel选择 processHTML 方法和 观察[=20] 中的结果解决了这个问题=] 它在 UI 线程上如下:

@Override
public void onViewCreated(View root, Bundle savedInstanceState) {
    super.onViewCreated(root, savedInstanceState);
    activity = getActivity();

    String urlToBeOpened = "http://ncrdb.usga.org";

    WebView webView = (WebView) root.findViewById(R.id.webView1);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
    webView.setWebViewClient(new WebViewClient(){
        @Override
        public void onPageFinished(WebView view, String url)
        {
            /* This call inject JavaScript into the page which just finished loading. */
            webView.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
        }
    });
    webView.loadUrl(urlToBeOpened);

    TeeboxViewModel teeboxViewModel = new ViewModelProvider((ViewModelStoreOwner) activity).get(TeeboxViewModel.class);
    teeboxViewModel.getSelected().observe(getViewLifecycleOwner(), item -> {
        ...
        NavController navController = Navigation.findNavController(activity, R.id.nav_host_fragment);
        navController.navigate(R.id.action_whsSearchWebDB_to_nav_newResult);
    });
}

public static class MyJavaScriptInterface {
    public static Map<String, String> coursesList = new HashMap<>();
    @JavascriptInterface
    public void processHTML(String html) {
            ...
            TeeboxViewModel model = new ViewModelProvider((ViewModelStoreOwner) activity).get(TeeboxViewModel.class);
            model.select(teeboxesList);
    }
}