Android freemarker模板引擎應用
什么是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'
2、將main.tpl文件放入assets目錄下
<!--main.tpl文件-->
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome ${user}!</h1>
<p>Our latest product:
</body>
</html>
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();
}
}
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();
}
}
}
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、為什么要先把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
官方說可以,但個人測試了無數遍,就是無法編譯對象傳值
如下方式可以獲取到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>
總結
最后沒發現webView頁面加載快多少,可能數據量少。畢竟要對SD卡操作。流量確實省了,也少了java和html直接的數據交互代碼。
當然你會用這玩意后,在老板面前就死命的推薦應用中多用html,省下一大筆時間
來自:http://www.androidchina.net/6533.html