Handling return non-callback method via WebView in react-native
This article mainly introduces the detailed explanation of react-native WebView return processing (can be solved by non-callback methods). Now I share it with you and give it as a reference.
1. Preface
There are some pages in the project that change frequently. We will consider using web pages to solve these pages.
Provide a public Web page in the RN project. If it is web content, jump to this interface for display.
At this time, there will be a problem that the web page will have a first-level page and a second-level page, which will be designed to handle the return key of the navigation bar (and the processing of the return key on Android).
The solution to this problem can be found on the RN official website. Just use the onNavigationStateChange callback method to record the current navigation state, so as to determine whether to return to the previous page or exit this webpage and return to other interfaces of the App.
However, when the implementation of the web page is React, there will be a problem. You will find that when the page jumps, the onNavigationStateChange callback method has no callback! ! ! How fat! !
At first, I tried to change the web address to Baidu's, which can receive callbacks. Everything ran very well, but it didn't work if I changed it to our link, so I passed the blame to the backend, thinking it was React. Which part is written incorrectly.
Because the last project was tight and I didn’t have time to take a good look at the source code, I thought of a not very complete solution, which is to use js on the web page to call back the App to inform the current navigation status. This solution The display is unfriendly.
Now I have a little time to read the source code and find out the real reason.
2. Reason
The following is an analysis of the cause of this problem and my solution.
1. First, find the location of the source code.
node_modules\react-native\ReactAndroid\src\main\java\com\facebook\react\views\webview
node_modules\react-native\Libraries\Components\WebView
The directory structure is like this:
2. Implemented code segment (JAVA side)
The actual running code of RN is native code, so some event callbacks like WebView components are actually triggered by callbacks in native code. As follows
(ReactWebViewManager.java) rn version 0.47.1
protected static class ReactWebViewClient extends WebViewClient { //WebViewClient就是我们在写Android原生代码时,监听网页加载情况使用的工具。 protected static final String REACT_CLASS = "RCTWebView"; //定义的原生组件名,在后面JS中会对应到。 //... @Override public void onPageStarted(WebView webView, String url, Bitmap favicon) { //有很多回调方法,此处只举一例 super.onPageStarted(webView, url, favicon); mLastLoadFailed = false; dispatchEvent( webView, new TopLoadingStartEvent( //自己定义的时间,dispatch后,事件会传给js webView.getId(), createWebViewEvent(webView, url))); } //... }
(ReactWebViewManager.java) rn version 0.43.3, RN different versions There will be code adjustments, so careful regression testing is required when RN is upgraded.
protected static class ReactWebViewClient extends WebViewClient { //WebViewClient就是我们在写Android原生代码时,监听网页加载情况使用的工具。 protected static final String REACT_CLASS = "RCTWebView"; //定义的原生组件名,在后面JS中会对应到。 //... @Override public void onPageStarted(WebView webView, String url, Bitmap favicon) { //有很多回调方法,此处只举一例 super.onPageStarted(webView, url, favicon); mLastLoadFailed = false; dispatchEvent( webView, new TopLoadingStartEvent( //自己定义的时间,dispatch后,事件会传给js webView.getId(), createWebViewEvent(webView, url))); } @Override public void doUpdateVisitedHistory(WebView webView, String url, boolean isReload) { //坑在这,这里就是导航有变化的时候会回调在这个版本是有这个处理的,但是不知道在哪个版本删掉了 -.- super.doUpdateVisitedHistory(webView, url, isReload); dispatchEvent( webView, new TopLoadingStartEvent( webView.getId(), createWebViewEvent(webView, url))); } //... }
(TopLoadingStartEvent.java) Callback JS Event
public class TopLoadingStartEvent extends Event<TopLoadingStartEvent> { public static final String EVENT_NAME = "topLoadingStart"; //对应方法是onLoadingStart, 因为对RN的结构不熟悉,在此处花了很长时间研究是怎么对应的,最后找到了定义对应的文件 private WritableMap mEventData; public TopLoadingStartEvent(int viewId, WritableMap eventData) { super(viewId); mEventData = eventData; } @Override public String getEventName() { return EVENT_NAME; } @Override public boolean canCoalesce() { return false; } @Override public short getCoalescingKey() { // All events for a given view can be coalesced. return 0; } @Override public void dispatch(RCTEventEmitter rctEventEmitter) { rctEventEmitter.receiveEvent(getViewTag(), getEventName(), mEventData); } }
(node_modules\ react-native\ReactAndroid\src\main\java\com\facebook\react\uimanager\UIManagerModuleConstants.java)
In this file, the corresponding relationship is defined
/** * Constants exposed to JS from {@link UIManagerModule}. */ /* package */ class UIManagerModuleConstants { /* package */ static Map getDirectEventTypeConstants() { return MapBuilder.builder() .put("topContentSizeChange", MapBuilder.of("registrationName", "onContentSizeChange")) .put("topLayout", MapBuilder.of("registrationName", "onLayout")) .put("topLoadingError", MapBuilder.of("registrationName", "onLoadingError")) .put("topLoadingFinish", MapBuilder.of("registrationName", "onLoadingFinish")) .put("topLoadingStart", MapBuilder.of("registrationName", "onLoadingStart")) .put("topSelectionChange", MapBuilder.of("registrationName", "onSelectionChange")) .put("topMessage", MapBuilder.of("registrationName", "onMessage")) .build(); } }
3. Implemented code snippet (JS side)
(node_modules\react-native\Libraries\Components\WebView\WebView.android.js)
You can see in the code below that only onLoadingStart and onLoadingFinish will call updateNavigationState. The problem arises here. Since our web page is implemented in React, there is only one page! So onLoadingStart and onLoadingFinish will only be called once. Clicking the details page again will not jump to a new page, but will refresh the original page. So there is no updateNavigationState callback.
class WebView extends React.Component { static propTypes = { //给外部定义的可设置的属性 ...ViewPropTypes, renderError: PropTypes.func, renderLoading: PropTypes.func, onLoad: PropTypes.func, //... } render() { //绘制页面内容 //... var webView = <RCTWebView ref={RCT_WEBVIEW_REF} key="webViewKey" style={webViewStyles} source={resolveAssetSource(source)} onLoadingStart={this.onLoadingStart} onLoadingFinish={this.onLoadingFinish} onLoadingError={this.onLoadingError}/>; return ( <View style={styles.container}> {webView} {otherView} </View> ); } onLoadingStart = (event) => { var onLoadStart = this.props.onLoadStart; onLoadStart && onLoadStart(event); this.updateNavigationState(event); }; onLoadingFinish = (event) => { var {onLoad, onLoadEnd} = this.props; onLoad && onLoad(event); onLoadEnd && onLoadEnd(event); this.setState({ viewState: WebViewState.IDLE, }); this.updateNavigationState(event); }; updateNavigationState = (event) => { if (this.props.onNavigationStateChange) { this.props.onNavigationStateChange(event.nativeEvent); } }; } var RCTWebView = requireNativeComponent('RCTWebView', WebView, { //对应上面JAVA中的 ‘RCTWebView' nativeOnly: { messagingEnabled: PropTypes.bool, }, }); module.exports = WebView;
2. Solution
Now that the cause is found, it is easy to solve
Solution: Customize WebView, add doUpdateVisitedHistory processing, and notify JS every time the navigation changes.
1. Copy the files in the picture below to the Android code directory in our own project
The Android directory after copying:
There are several places that need to be modified in ReactWebViewManager.java
public class ReactWebViewManager extends SimpleViewManager<WebView> { protected static final String REACT_CLASS = "RCTWebView1"; //此处修改一下名字 protected static class ReactWebViewClient extends WebViewClient { @Override public void doUpdateVisitedHistory(WebView webView, String url, boolean isReload) { super.doUpdateVisitedHistory(webView, url, isReload); dispatchEvent( //在导航变化的时候,dispatchEvent webView, new TopCanGoBackEvent( webView.getId(), createCanGoBackWebViewEvent(webView, url))); } } }
TopCanGoBackEvent is an Event I added myself, specifically for To notify navigation changes
TopCanGoBackEvent.java
public class TopCanGoBackEvent extends Event<TopCanGoBackEvent> { public static final String EVENT_NAME = "topChange"; private WritableMap mEventData; public TopCanGoBackEvent(int viewId, WritableMap eventData) { super(viewId); mEventData = eventData; } @Override public String getEventName() { return EVENT_NAME; } @Override public boolean canCoalesce() { return false; } @Override public short getCoalescingKey() { // All events for a given view can be coalesced. return 0; } @Override public void dispatch(RCTEventEmitter rctEventEmitter) { rctEventEmitter.receiveEvent(getViewTag(), getEventName(), mEventData); } }
New ReactWebViewPage.java
public class ReactWebViewPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Arrays.<ViewManager>asList( new ReactWebViewManager() ); } }
Then add this module in MainApplication
public class MainApplication extends Application implements ReactApplication { @Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new ReactWebViewPackage() //WebView ); } }
The above is what needs to be modified for Android. I have not tried it for ios. It should be quite different. A truth.
2. Copy the file in the picture below to the JS code directory in our own project, and change the name
JS代码目录:
CustomWebView.android.js 有几个地方需要修改。
/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule CustomWebView //此处需要修改名称 */ var RCT_WEBVIEW_REF = 'webview1'; //此处需要修改名称 render() { var webView = <NativeWebView onLoadingStart={this.onLoadingStart} onLoadingFinish={this.onLoadingFinish} onLoadingError={this.onLoadingError} onChange={this.onChange} //添加方法 />; return ( <View style={styles.container}> {webView} {otherView} </View> ); } onChange = (event) => { //添加方法 this.updateNavigationState(event); }; } var RCTWebView = requireNativeComponent('RCTWebView1', CustomWebView, CustomWebView.extraNativeComponentConfig); //修改名称 module.exports = CustomWebView; //修改名称
至此就完成自定义WebView模块。也可以解决网页是React实现,不能导航的问题。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
在vue中如何解决v-for使用报红并出现警告的问题(详细教程)
The above is the detailed content of Handling return non-callback method via WebView in react-native. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

1. Log output to file using module: logging can generate a custom level log, and can output the log to a specified path. Log level: debug (debug log) = 5) {clearTimeout (time) // If all results obtained 10 consecutive times are empty Log clearing scheduled task}return}if(data.log_type==2){//If a new log is obtained for(i=0;i

Use the new JavaFXWebView component in Java13 to display web content. With the continuous development of Java, JavaFX has become one of the main tools for building cross-platform graphical interfaces. JavaFX provides a wealth of graphics libraries and components, allowing developers to easily create a variety of user interfaces. Among them, the JavaFXWebView component is a very useful component that allows us to display web content in JavaFX applications. In Java13, J

Introduction to Caddy Caddy is a powerful and highly scalable web server that currently has 38K+ stars on Github. Caddy is written in Go language and can be used for static resource hosting and reverse proxy. Caddy has the following main features: Compared with the complex configuration of Nginx, its original Caddyfile configuration is very simple; it can dynamically modify the configuration through the AdminAPI it provides; it supports automated HTTPS configuration by default, and can automatically apply for HTTPS certificates and configure it; it can be expanded to data Tens of thousands of sites; can be executed anywhere with no additional dependencies; written in Go language, memory safety is more guaranteed. First of all, we install it directly in CentO

Form validation is a very important link in web application development. It can check the validity of the data before submitting the form data to avoid security vulnerabilities and data errors in the application. Form validation for web applications can be easily implemented using Golang. This article will introduce how to use Golang to implement form validation for web applications. 1. Basic elements of form validation Before introducing how to implement form validation, we need to know what the basic elements of form validation are. Form elements: form elements are

Using Jetty7 for Web Server Processing in JavaAPI Development With the development of the Internet, the Web server has become the core part of application development and is also the focus of many enterprises. In order to meet the growing business needs, many developers choose to use Jetty for web server development, and its flexibility and scalability are widely recognized. This article will introduce how to use Jetty7 in JavaAPI development for We

Face-blocking barrage means that a large number of barrages float by without blocking the person in the video, making it look like they are floating from behind the person. Machine learning has been popular for several years, but many people don’t know that these capabilities can also be run in browsers. This article introduces the practical optimization process in video barrages. At the end of the article, it lists some applicable scenarios for this solution, hoping to open it up. Some ideas. mediapipeDemo (https://google.github.io/mediapipe/) demonstrates the mainstream implementation principle of face-blocking barrage on-demand up upload. The server background calculation extracts the portrait area in the video screen, and converts it into svg storage while the client plays the video. Download svg from the server and combine it with barrage, portrait

First of all, you will have a doubt, what is frp? Simply put, frp is an intranet penetration tool. After configuring the client, you can access the intranet through the server. Now my server has used nginx as the website, and there is only one port 80. So what should I do if the FRP server also wants to use port 80? After querying, this can be achieved by using nginx's reverse proxy. To add: frps is the server, frpc is the client. Step 1: Modify the nginx.conf configuration file in the server and add the following parameters to http{} in nginx.conf, server{listen80

Web standards are a set of specifications and guidelines developed by W3C and other related organizations. It includes standardization of HTML, CSS, JavaScript, DOM, Web accessibility and performance optimization. By following these standards, the compatibility of pages can be improved. , accessibility, maintainability and performance. The goal of web standards is to enable web content to be displayed and interacted consistently on different platforms, browsers and devices, providing better user experience and development efficiency.
