現在的移動端開發中,越來越多的開發人員在使用混合式開發的模式;加載友善,布局簡單,不占用手機記憶體等等優點使得混合式開發的項目讓越來越多的人喜歡,現在我就給大家介紹兩種不同的純Android和H5界面之間的互動方式,由于技術淺薄,很多地方可能存在缺漏,歡迎大家批評指正!
第一種方式很簡單,隻要簡單的進行加載H5界面就可以,這種加載方式比較适合初學者使用,因為大部分的資料渲染的工作可能會放在h5界面中進行,但是同樣也存在界面穩定性不是很高的現象,下面我們來看下這個代碼:
Intent i = new Intent();
i.setClass(context, WebActivity.class);
AppInfoHelper.clearParamForWebPage();
AppInfoHelper.setParamForWebPage(2, data.getResourceId());
i.putExtra("url", Const.H5URL.URL_LOAN_APPLY_DETAIL);
context.startActivity(i);
上面的邏輯中其實就是一個很簡單的頁面跳轉邏輯,其中的WebActiity是用來加載所有的h5界面的一個通用類,所有的h5加載方法均調用這個類對h5的界面進行加載,data是上一個頁面中擷取到的資料,或者本頁面中通路網絡擷取到的資料,把對應的想傳遞的通過上面的形式塞到h5界面中,AppInfoHelper是一個用來存儲使用者資訊的工具類,相當于是SharedPreference,所添加的參數url就是我們app項目中的h5界面的目标檔案夾,如下所示:
public class Const {
public interface H5URL{
String URL_LOAN_APPLY_LIST = "file:///android_asset/mobile-page/html/loan-apply/loan-apply.html";
String URL_FINANCING_APPLY_LIST = "file:///android_asset/mobile-page/html/finance-need/finance-need.html";
String URL_FINANCING_APPLY_DETAIL = "file:///android_asset/mobile-page/html/finance-need/finance-need-detail.html";
String URL_LOAN_APPLY_DETAIL = "file:///android_asset/mobile-page/html/loan-apply/loan-apply-detail.html";
}
第二種方式可能會比較複雜一些,但是大多數的操作是在我們Android這邊完成,對每一個控件的點選跳轉進行提前設定,并且擷取到資料,直接塞到h5界面中進行渲染,但是這種方法會大大增加android端的開發工作量,是以還是謹慎選擇為好,廢話少說,上代碼:
//初始化webView
webView = new BaseWebView(this);
webView.getSettings().setSupportZoom(false);
webView.getSettings().setDisplayZoomControls(false);
webView.getSettings().setTextSize(WebSettings.TextSize.NORMAL);
//加載頁面
webView.loadUrl("file:///android_asset/mobile-page/html/fun.html");
//注冊元件
webView.registerComponents("BaseComponents", new WebComponents());
llLayout.addView(webView);
其中的BaseWebView是我自己封裝的一個基礎類,裡面包含了一些擷取焦點的方法等;直接通過loadUrl進行asset目錄下的html檔案的加載,然後通過注冊元件把資料塞到這個界面中進行處理最後再調用addview的方法将這個界面在目标的布局檔案中進行顯示,下面貼出的代碼是WebComponents的邏輯:
/**
* 與HTML5互動的元件
*/
public class WebComponents extends AbsComponents {
@Override
protected ComponentsResult onExec(String action, String callBackMethod, JSONArray params) throws Exception {
L.d("action:" + action + ", callBackMethod:" + callBackMethod
+ ", params:" + params.toString());
//擷取資料
if ("data".equals(action)) {
String type = params.getString(0);
if ("page".equals(type)) {
Map<String, String> map = new HashMap<>();
map.put("page", "YSWS");//吃喝玩樂
webView.loadFrameJavaScript("", new Gson().toJson(map), callBackMethod);
}
//擷取字典表資料
else if ("type".equals(type)) {
getTypeInfo(params.getString(1), callBackMethod);
}
//擷取地區資訊
else if ("range".equals(type)) {
getAreaInfo(callBackMethod);
}
//擷取資料清單
else if ("list".equals(type)) {
JsonObject jo = new JsonParser().parse(params.getString(1)).getAsJsonObject();
String serviceType = jo.get("serviceTypeOne").getAsString();
String sort = jo.get("sort").getAsString();
String pageSize = jo.get("pageSize").getAsString();
String currentPageNo = jo.get("currentPage").getAsString();
getYswsInfo(serviceType, sort, pageSize, currentPageNo, callBackMethod);
}
}
//點選事件
else if ("click".equals(action)) {
String data = params.getString(0);
JsonObject jo = new JsonParser().parse(data).getAsJsonObject();
Intent intent = new Intent(YswsActivity.this, ChwlDetailActivity.class);
if (jo.has("linkUrl") && StringUtils.isNotBlank(jo.get("linkUrl").getAsString())) {
intent.putExtra(SysCode.INTENT_PARAM.URL, jo.get("linkUrl").getAsString());
} else {
BaseToast.showToastNotRepeat(YswsActivity.this, "url位址為空", SysCode.TOAST_TIME);
return null;
}
intent.putExtra(SysCode.INTENT_PARAM.TITLE, jo.get("placeTypeValue").getAsString() + "詳情");
intent.putExtra(SysCode.INTENT_PARAM.ACTIVITY, "YswsActivity");
intent.putExtra("detail", new Gson().fromJson(data, TourBean.class));
startActivity(intent);
}
return null;
}
@Override
protected void onInit(Context ctx, BrowserCore browserCore) {
}
}
邏輯中與action相對應的參數是和h5界面的開發人員協調完成以後,設定的通用參數,在h5界面中可以直接根據這個參數擷取相對應的資料和操作!AbsComponent是一個自己封裝的塞資料的基礎類,邏輯如下所示:
public abstract class AbsComponents implements Components {
private static final String TAG = "Business_Components";
protected static final String OK = JSONObject.quote("OK");
protected static final String ERROR = JSONObject.quote("Error");
protected static final String EMPTY = JSONObject.quote((String)null);
private Context mContext;
private BrowserCore mBrowserCore;
private AbsComponents.ComponentHandler mHandler;
public AbsComponents() {
}
public void initComponents(Context context, BrowserCore browserCore) {
if(null != context) {
this.mContext = context;
}
this.mBrowserCore = browserCore;
this.mHandler = new AbsComponents.ComponentHandler();
this.onInit(this.mContext, browserCore);
}
public final void init(Context context, BrowserCore browserCore) {
}
public final ComponentsResult exec(String arg0, String callBackMethod, String arg1) {
if(TextUtils.isEmpty(arg0)) {
LogUtil.i("Business_Components", "exec action is empty");
return null;
} else {
try {
JSONArray e = new JSONArray(arg1);
return this.onExec(arg0, callBackMethod, e);
} catch (Exception var5) {
LogUtil.e("Business_Components", "errorMsg:" + var5.getMessage(), var5);
return null;
}
}
}
public final void onDestroy() {
}
protected Context getContext() {
return this.mContext;
}
protected BrowserCore getBrowserCore() {
return this.mBrowserCore;
}
protected AbsComponents.ComponentHandler getComponentHandler() {
return this.mHandler;
}
protected void sendHandlerMessage(int what, Object object) {
if(null != this.mHandler) {
Message message = this.mHandler.obtainMessage();
message.what = what;
message.obj = object;
this.mHandler.sendMessage(message);
}
}
protected String parseJsCallback(String jsMethod, String params) {
if(TextUtils.isEmpty(jsMethod)) {
LogUtil.i("Business_Components", "parseJsCallback jsMethod is empty");
return null;
} else {
StringBuilder stringBuilder = new StringBuilder(jsMethod);
stringBuilder.append("(\'");
if(!TextUtils.isEmpty(params)) {
stringBuilder.append(params);
}
stringBuilder.append("\')");
return stringBuilder.toString();
}
}
protected abstract ComponentsResult onExec(String var1, String var2, JSONArray var3) throws Exception;
protected abstract void onInit(Context var1, BrowserCore var2);
protected void onHandleMessage(Message message) {
}
private class ComponentHandler extends Handler {
private ComponentHandler() {
}
public void handleMessage(Message msg) {
super.handleMessage(msg);
AbsComponents.this.onHandleMessage(msg);
}
}
}
在塞資料的過程中會涉及到擷取網絡資料的方法,這個網絡架構的封裝 我會在接下來的博文中做詳細的表述,僅僅貼出代碼,供大家欣賞!(擷取地區資訊的方法)
/**
* 擷取區域
*
* @param jsMethod
*/
private void getAreaInfo(String jsMethod) {
//請求資料
Map<String, String> dataMap = new HashMap<String, String>();
dataMap.put("code", application.getString(SysCode.SHAREDPREFERENCES.CITY_CODING));//從本地資料庫擷取地市編碼360500000000
Map<String, String> map = CommUtil.requestData(ConfigUtil.IS_SECURITY
, SysCode.REQUEST_CODE.GET_CODE, dataMap, getApplicationContext());
mVolleyUtil.init("", map, SysCode.HANDLE_MSG.HANDLER_SECOND,
SysCode.REQUEST_POST, false, false, "", jsMethod);
}
以上就是本人總結的Android和h5之間互動的相關邏輯,如果大家想要代碼參考,可以在下面進行留言,多謝!!!!
我是IT老王,熱愛程式設計,熱愛生活!!!!!!