Android freemarker模板引擎应用

移动开发 Android
什么是freemarker?简单点就是,事先把上面这个html文件,放到应用中,用的时候只要传入数据就行。

什么是freemarker?

在说这个之前我们都知道web和原生控件之争就那么点事。性能,加载速度,流量,数据交互….

如果我用webView加载一个url页面,要先通过网络解析css,解析html代码,然后渲染生成页面

什么是freemarker?简单点就是,事先把上面这个html文件,放到应用中,用的时候只要传入数据就行

freemarker优点和应用

节约流量,加快网页加载速度

比如某些图表功能,用js库实现比较方便,只要事先放入html模板,传入数据就行。大大节省了流量及加载速度

或者事先已经有网页功能的页面,就不需要在制作Android界面了

此功能在IOS上通用,所以只要一个模板,就可以用在IOS和Android上,大大节约开发时间

实现原理

webView加载本地模板引擎流程

main.tpl ——–> main.ftl+数据 ———> main.html ———> webView.load(main.html)

1、导入freemarker库

compile 'org.freemarker:freemarker-gae:2.3.25-incubating' 
  • 1.

2、将main.tpl文件放入assets目录下

<!--main.tpl文件--> 
<html> 
<head> 
  <title>Welcome!</title> 
</head> 
<body> 
  <h1>Welcome ${user}!</h1> 
  <p>Our latest product: 
</body> 
</html>  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

3、根据main.tpl转成main.ftl

private void prepareTemplate() throws IOException { 
    //获取app目录  data/data/package/file/ 
    String destPath = getFilesDir().getAbsolutePath(); 
    File dir = new File(destPath); 
    //判断文件夹是否存在并创建 
    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(); 
    } 
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

4、将 main.ftl和数据 生成main.html文件

private void genHTML(Product object) { 
    String destPath = getFilesDir().getAbsolutePath(); 
    FileWriter out = null
    //数据源 
    Map root = new HashMap(); 
    root.put("user""user");   //传入字符串 
    //root.put("product", object.url());     //传入对象(会报错) 
    try { 
        Configuration cfg = new Configuration(new Version(2,3,0)); 
        cfg.setDefaultEncoding("UTF-8");   
        //设置报错提示 
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 
        //设置报错提示 
        cfg.setLogTemplateExceptions(true); 
        out = new FileWriter(new File(destPath + "main.html")); 
        //设置.ftl模板文件路径 
        cfg.setDirectoryForTemplateLoading(new File(destPath)); 
        //设置template加载的.ftl模板文件名称 
        Template temp = cfg.getTemplate("main.ftl"); 
        //讲数据源和模板生成.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(); 
        } 
    } 
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.

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); 
    } 
});  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

问题注意点

1、为什么要先把mian.tpl转成main.ftl文件,而不直接把mian.ftl文件放到assets中,然后template直接加载main.ftl文件

因为assets中的文件无法直接读取,所以要先把文件放到data/data/package/….再操作

2、突然发现2016年版的freemarker无法传递对象。

比如在main.ftl文件中${model.name}就无法再继续转成main.html,提示如下错误

Unresolved exception class when finding catch block: java.beans.IntrospectionException 
  • 1.

官方说可以,但个人测试了无数遍,就是无法编译对象传值

如下方式可以获取到name

//activity.java 
User user = new User(); 
user.setName="张三" 
Map map = HashMap(); 
map.put("name"user.getName()); 
 
//main.tpl 
<html> 
<body> 
  ${name
<body> 
<html>  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

如下方式无法获取到name

//activity.java 
User user = new User(); 
user.setName="张三" 
Map map = HashMap(); 
map.put("user"user); 
 
//main.tpl 
<html> 
<body> 
  ${user.name
<body> 
<html>  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

总结

***没发现webView页面加载快多少,可能数据量少。毕竟要对SD卡操作。流量确实省了,也少了java和html直接的数据交互代码。

责任编辑:庞桂玉 来源: Android开发中文站
相关推荐

2012-03-06 15:34:05

JavaFreeMarker

2017-03-13 11:11:20

AndroidAndroid Stu文件组

2021-01-11 13:46:26

Spring BootThymeleafJava

2023-05-14 17:16:22

分类树SpringBoot

2017-01-04 15:22:57

TrimPath模板引擎

2011-07-07 16:15:20

Smarty

2012-02-29 13:39:18

AndroidGoogle

2011-07-15 14:01:50

PHP模板引擎

2023-11-10 09:16:45

SpringBootThymeleaf

2012-04-30 20:54:01

Android

2019-11-13 09:01:48

开源JavaScript模板引擎

2017-07-06 14:32:27

静态化FreeMarkerjava

2011-03-02 13:41:34

Action BarDashboardAndroid用户界面

2024-11-29 12:58:13

2020-10-19 11:49:32

NodeJavaScript

2014-05-16 11:09:38

Handlebars模板引擎

2022-04-15 07:21:12

架构开源模板引擎

2013-08-20 18:50:46

JS模板引擎模块化Web App

2016-11-01 20:26:47

前端模板underscoreWeb

2009-12-23 18:06:25

WPF模板
点赞
收藏

51CTO技术栈公众号