Android freemarker模板引擎應(yīng)用
什么是freemarker?
在說這個(gè)之前我們都知道web和原生控件之爭(zhēng)就那么點(diǎn)事。性能,加載速度,流量,數(shù)據(jù)交互….
如果我用webView加載一個(gè)url頁(yè)面,要先通過網(wǎng)絡(luò)解析css,解析html代碼,然后渲染生成頁(yè)面
什么是freemarker?簡(jiǎn)單點(diǎn)就是,事先把上面這個(gè)html文件,放到應(yīng)用中,用的時(shí)候只要傳入數(shù)據(jù)就行
freemarker優(yōu)點(diǎn)和應(yīng)用
節(jié)約流量,加快網(wǎng)頁(yè)加載速度
比如某些圖表功能,用js庫(kù)實(shí)現(xiàn)比較方便,只要事先放入html模板,傳入數(shù)據(jù)就行。大大節(jié)省了流量及加載速度
或者事先已經(jīng)有網(wǎng)頁(yè)功能的頁(yè)面,就不需要在制作Android界面了
此功能在IOS上通用,所以只要一個(gè)模板,就可以用在IOS和Android上,大大節(jié)約開發(fā)時(shí)間
實(shí)現(xiàn)原理
webView加載本地模板引擎流程
main.tpl ——–> main.ftl+數(shù)據(jù) ———> main.html ———> webView.load(main.html)
1、導(dǎo)入freemarker庫(kù)
- compile 'org.freemarker:freemarker-gae:2.3.25-incubating'
2、將main.tpl文件放入assets目錄下
- <!--main.tpl文件-->
- <html>
- <head>
- <title>Welcome!</title>
- </head>
- <body>
- <h1>Welcome ${user}!</h1>
- <p>Our latest product:
- </body>
- </html>
3、根據(jù)main.tpl轉(zhuǎn)成main.ftl
- private void prepareTemplate() throws IOException {
- //獲取app目錄 data/data/package/file/
- String destPath = getFilesDir().getAbsolutePath();
- File dir = new File(destPath);
- //判斷文件夾是否存在并創(chuàng)建
- if (!dir.exists()) {
- dir.mkdir();
- }
- //需要生成的.ftl模板文件名及路徑
- String tempFile = destPath + "/" + "main.ftl";
- if (!(new File(tempFile).exists())) {
- //獲取assets中.tpl模板文件
- InputStream is = getResources().getAssets().open("main.tpl");
- //生成.ftl模板文件
- FileOutputStream fos = new FileOutputStream(tempFile);
- byte[] buffer = new byte[7168];
- int count = 0;
- while ((count = is.read(buffer)) > 0) {
- fos.write(buffer, 0, count);
- }
- fos.flush();
- fos.close();
- is.close();
- }
- }
4、將 main.ftl和數(shù)據(jù) 生成main.html文件
- private void genHTML(Product object) {
- String destPath = getFilesDir().getAbsolutePath();
- FileWriter out = null;
- //數(shù)據(jù)源
- Map root = new HashMap();
- root.put("user", "user"); //傳入字符串
- //root.put("product", object.url()); //傳入對(duì)象(會(huì)報(bào)錯(cuò))
- try {
- Configuration cfg = new Configuration(new Version(2,3,0));
- cfg.setDefaultEncoding("UTF-8");
- //設(shè)置報(bào)錯(cuò)提示
- cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
- //設(shè)置報(bào)錯(cuò)提示
- cfg.setLogTemplateExceptions(true);
- out = new FileWriter(new File(destPath + "main.html"));
- //設(shè)置.ftl模板文件路徑
- cfg.setDirectoryForTemplateLoading(new File(destPath));
- //設(shè)置template加載的.ftl模板文件名稱
- Template temp = cfg.getTemplate("main.ftl");
- //講數(shù)據(jù)源和模板生成.html文件
- temp.process(root, out);
- out.flush();
- } catch (MalformedTemplateNameException e) {
- } catch (IOException e) {
- } catch (Exception e){
- }finally {
- try {
- if (out != null)
- out.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
5、webView加載main.html
- webview.post(new Runnable() {
- @Override
- public void run() {
- String templateDirRoot = getFilesDir().getAbsolutePath();
- String url = "file://" + templateDirRoot + "main.html";
- webview.loadUrl(url);
- }
- });
問題注意點(diǎn)
1、為什么要先把mian.tpl轉(zhuǎn)成main.ftl文件,而不直接把mian.ftl文件放到assets中,然后template直接加載main.ftl文件
因?yàn)閍ssets中的文件無法直接讀取,所以要先把文件放到data/data/package/….再操作
2、突然發(fā)現(xiàn)2016年版的freemarker無法傳遞對(duì)象。
比如在main.ftl文件中${model.name}就無法再繼續(xù)轉(zhuǎn)成main.html,提示如下錯(cuò)誤
- Unresolved exception class when finding catch block: java.beans.IntrospectionException
官方說可以,但個(gè)人測(cè)試了無數(shù)遍,就是無法編譯對(duì)象傳值
如下方式可以獲取到name
- //activity.java
- User user = new User();
- user.setName="張三"
- Map map = HashMap();
- map.put("name", user.getName());
- //main.tpl
- <html>
- <body>
- ${name}
- <body>
- <html>
如下方式無法獲取到name
- //activity.java
- User user = new User();
- user.setName="張三"
- Map map = HashMap();
- map.put("user", user);
- //main.tpl
- <html>
- <body>
- ${user.name}
- <body>
- <html>
總結(jié)
***沒發(fā)現(xiàn)webView頁(yè)面加載快多少,可能數(shù)據(jù)量少。畢竟要對(duì)SD卡操作。流量確實(shí)省了,也少了java和html直接的數(shù)據(jù)交互代碼。