本文目錄一覽:
- 1、hybrid App中js調用native接口原理
- 2、怎麼在web worker啟動的js線程調用native.js
- 3、在Android上怎樣實現JAVA和JS交互
- 4、react-native: ios原生調用js方法
- 5、native與JS簡單交互
- 6、js調用Native
hybrid App中js調用native接口原理
移動網絡的發展推動移動APP盛行,目前市場上APP開發技術的類型主要有三種,native開發、hybrid開發、RN/weex開發。
本文主要講述hybrid APP中js調用native原理。hybrid APP就是利用Android/iOS上webview加載web網頁,其實就是相當於用native做了一個外殼,然后里面加載網頁。那站在業務層面上,只要沒有太依賴性能,都能滿足需求,那這裡面有可能會用到一些硬件功能,比如:相機、位置等,這時就必須調用native。
1.js 調用 native,Android裡面主要通過WebViewClient.shouldOverrideUrlLoading方法攔截指定格式的URL,通過攔截特定URL和獲取對應的參數,來調用native對應的功能。這裡我們主要通過cordova插件,來做例子說明
上面我們看到cordova的初始化,這裡面主要對回調callback進行定義,js調用native之後,native處理完結果,將結果返回js,就是通過callback完成。
3.構造鏈接,並發送鏈接pokeNative
這裡我們看到調用native可以通過iframe和通過XHR完成。
這就是js調用native的方式,native完成處理之後,通過webView.addJavascriptInterface調用js中掛載在window對象的方法,這是一個統一的回調nativeCallback ,通過callbackID識別出本次結果需要回調js中的哪個function。然後本次交互就全部完成了
總結一下,主要同理是通過native兩個方法:addJavascriptInterface和shouldOverrideUrlLoading完成js和native交互。
怎麼在web worker啟動的js線程調用native.js
HTML5-Web Workers實現多線程:
當在 HTML 頁面中執行腳本時,頁面的狀態是不可響應的,直到腳本已完成。雖然在JavaScript中有setInterval和setTimeout函數使javaScript看起來好像使多線程執行,單實際上JavaScript使單線程的,一次只能做一件事情。
可以運行以下示例,檢驗js的單線程特性。
相關代碼請到github查看。
div id=’container’/div
script
window.alert(‘hi’);
setTimeout(function(){
var ul = document.createElement(‘ul’);
var li = document.createElement(‘li’);
var text = document.createTextNode(‘world’);
var container = document.getElementById(‘container’);
li.appendChild(text);
ul.appendChild(li);
container.appendChild(ul);
console.log(‘done!’);
},2000);
/script123456789101112131415123456789101112131415
如果JavaScript是多線程,在彈出警告框兩秒後,頁面應該出現一個li標籤(內容為world)。事實上因為JavaScript是單線程,所以如果你不點擊彈出框的確定按鈕,world這個li永遠也出不來。
點擊確定後
web worker 是運行在後台的 JavaScript,獨立於其他腳本,不會影響頁面的性能。您可以繼續做任何願意做的事情:點擊、選取內容等等,而此時 web worker 在後台運行。
我們需要把希望單獨執行的javascript代碼放到一個單獨的js文件中,然後在頁面中調用Worker構造函數來創建一個線程,參數是該文件路徑,參數存放如果是相對地址,那麼要以包含調用Worker構造函數語句所在腳本為參照,如果是絕對路徑,需要保證同源(協議+主機+端口)。這個文件不需要我們在頁面使用script標籤顯示引用。
var worker = new Worker(‘src/js/worker.js’);11
我們可以看到worker對象只有兩個屬性,其實是兩個回調函數句柄
onerror:當worker運行出現錯誤,並且沒有在worker中ing捕獲,會在此捕獲
onmessage:當worker向主線程發送消息是調用
在其prototype內有兩個重要方法
postMessage:很熟悉的趕腳,之前我們介紹過window對象的postMessage()方法,woker的postMessage方法和window的比較類似,但參數略有不同,只需要傳遞消息內容就可以,而且支持所有JavaScript原生數據類型,當然不放心的話同樣也可以序列化為字符串傳遞
terminate:終止worker執行,有些worker執行比較慢,主線程可以主動終止其執行
下面我們用web workers重寫上面那個例子。
相關代碼請到github查看。
test_web_worker.html
script
var worker = new Worker(‘./worker.js’);
window.alert(‘hi’);
/script12341234
worker.js
setTimeout(function(){console.log(‘done!’);},2000);
在Android上怎樣實現JAVA和JS交互
在Android的開發過程中、遇到一個新需求、那就是讓Java代碼和Javascript代碼進行交互、在IOS中實現起來很麻煩、而在Android中相對來說容易、Android對這種交互進行很好的封裝、其實可以很簡單的用Java代碼調用WebView中的js函數、也可以用WebView中的js來調用Android應用中的Java代碼
一、網頁的JS代碼調用ANDROID中JAVA代碼的方法
在網頁中調用java代碼、需要在webview控件中添加javascriptInterface
contentWebView = (WebView) findViewById(R.id.webview);
//啟用javascript
contentWebView.getSettings().setJavaScriptEnabled(true);
contentWebView.addJavascriptInterface(this, “js對象名”);
在Activity中定義一個要被js調用的方法、src為js傳遞過來的參數、如果沒有不傳也可以的。
public void jsFunction(final String str) {
Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
runOnUiThread(new Runnable() {
@Override
public void run() {
//在里對Android應用的UI進行處理
}
});
}
在網頁中、只需要像調用js方法一樣、進行調用就可以
a onClick=”window.js對象名.jsFunction(´hello world´)”
點擊調用java代碼並傳遞參數
/a
二、ANDROID中JAVA代碼調用網頁的JS代碼的方法
Java代碼調用js並傳參其實是通過WebView的loadUrl方法去調用的、只是參數url的寫法不一樣
// 無參數調用
contentWebView.loadUrl(“javascript:javacalljs()”);
// 傳遞參數調用
contentWebView.loadUrl(“javascript:javacalljswithargs(“
+ “´hello world´” + “)”);
三、JAVA和JS交互注意事項
1、Java 調用 js 裡面的函數、效率並不是很高、估計要200ms左右吧、做交互性很強的事情、這種速度很難讓人接受、而js去調Java的方法、速度很快、50ms左右、所以盡量用js調用Java方法
2、Java 調用 js 的函數、沒有返回值、調用就控制不到
3、Js 調用 Java 的方法、返回值如果是字符串、你會發現這個字符串是 native 的、轉成 locale 的才能正常使用、使用 toLocaleString() 函數就可以、不過這個函數的速度並不快、轉化的字符串如果很多、將會很耗費時間
4、網頁中盡量不要使用jQuery、執行起來需要5-6秒、最好使用原生的js寫業務腳本、以提升加載速度、改善用戶體驗
react-native: ios原生調用js方法
ReactEventEmit.h
#import React/RCTEventEmitter.h
#import React/RCTBridgeModule.h
@interface ReactEventEmit : RCTEventEmitterRCTBridgeModule
-(void)goToCashier:(NSString*) result;
@end
ReactEventEmit.m
#import “ReactEventEmit.h”
@implementation ReactEventEmit
@synthesize bridge = _bridge;
RCT_EXPORT_MODULE(ReactEventEmit);
+ (id)allocWithZone:(NSZone*)zone {
staticReactEventEmit*sharedInstance =nil;
staticdispatch_once_tonceToken;
dispatch_once(onceToken, ^{
sharedInstance = [superallocWithZone:zone];
});
returnsharedInstance;
}
-(NSArray *)supportedEvents{
return @[@”goToCashier”];
}
-(void)goToCashier:(NSString*) result
{
NSLog(@”======== cashierSuccess ========== %@”,result);
[self sendEventWithName:@”goToCashier” body:@{@”result”: result}];
}
@end
RN的module初始化是由RN內部實現的,所以我們調用這個實例的時候,必須是這樣子:
ReactEventEmit *emit = [ReactEventEmit allocWithZone:nil];
[emit goToCashier:@”fail”];
JS端調用:
const ReactEventEmit = NativeModules.ReactEventEmit;
const myReactEventEmit = new NativeEventEmitter(ReactEventEmit);
this.listener = myReactEventEmit.addListener(‘goToCashier’, (data: { result: string }) = {
console.warn(‘====== cashierSuccess ======= ‘ + JSON.stringify(data));
this.process(data.result);
});
native與JS簡單交互
使用 UIWebView 的 – (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script; 方法,就可以調用JS的方法了.
點擊網頁上的某個按鈕,想要執行native的某個方法.
比如,網頁上有一個分享按鈕,點擊後彈出分享平台選擇view,但這個view及彈齣動畫都是native這邊實現的.所以此時JS需要調用native方法,並將分享內容參數傳給native.
思路:給JS中的元素橋接一個native的對象或函數.這樣點擊網頁上的分享按鈕時,就可以執行native的方法了.
上面的思路如何實現呢?
系統已經為我們提供了相關API,那就是OC的JSContext類的類別SubscriptSupport提供的方法
– (void)setObject:(id)object forKeyedSubscript:(NSObject NSCopying *)key;
Use this method (or Objective-C subscript syntax) to bridge native objects or functions for use in JavaScript.
object參數通常是一個block對象.上述方法也可以使用下標語法: context[@”xxx”] = ^{};
當webView加載完成後,在該代理方法里實現.
這樣當用戶點擊js上的分享按鈕時,就可以彈出本地的分享選擇視圖了.
由於不太懂HTML5和JavaScript,所以上面有些地方的表述可能並不恰當.
js調用Native
JS 調用prompt方法,Android收到回調onJSPrompt 將native bridges方法註冊給js.window,然後js就可以調用iframe.scr 打開scheme,native端就可以在shouldOverrideUrlLoading()對scheme進行攔截解析處理
2.解析uri,從namespaceMap中根據module獲取最終AbstractBridgeModule的實現類
3.通過方法註解
shouldOverrideUrlLoading調用時機:二級鏈接
原創文章,作者:VFHY,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/132446.html