對標小程式 ? "快應用"開發入門指南
本文已在我的公眾號:hongyangAndroid原創首發;
一、快應用的出現
3月20日,中國通訊院等協會聯合包括小米、華為、OPPO等手機廠商,共同在北京正式釋出名為「快應用」的新型應用形態協議。
本來沒怎麼關注,不過就在今天,意外在小米、華為在看到了快應用的身影。當看到餓了麼的快應用的時候,才為之震驚,體驗相當好,仔細檢視佈局也為原生布局。
我們一起看一下,在小米應用商店,搜尋餓了麼:
可以看到下面的秒開,開啟後我錄製了一個gif:
基本上已經能滿足快速的需要了,整理體驗非常不錯,特意開了下佈局看了下:
原生控制元件,底部的列表,你還可以看到是個RecyclerView…
當然餓了麼的微信小程式做的也不錯,不過微信小程式並非轉化為原生元件。
並非只有餓了麼,已經上線了不少快應用,剛好身邊還有部華為,華為的快應用入口為:
華為應用市場,搜尋:快應用。
點選檢視更多:
可以看到一批應用的快應用已經上線了。
關鍵是體驗相當不錯,體積也很小。
雖然大家多數都為Android開發者,所幸的是開發一個快應用並不複雜,下面我們帶大家一起入門一個玩Android的快應用。
二、上手開發快應用
既然是入門教程,重點其實是環境搭建和基礎的使用,所以我們的形態是:
- 顯示一個文字列表,支援上拉載入
- 點選單個文章,跳轉到詳情頁
2.1 搭建環境
環境搭建可以直接參考開發文件,基本一樣
2.1.1 安裝nodejs
由於本人是MAC,以下教程針對MAC。
首先需要安裝nodejs,注意官網上提示版本需要6.0以上,8.0以下。
我裝了個7.0,你可以點選這裡下載安裝:
2.1.2 安裝hap-toolkit
npm install -g hap-toolkit
安裝完成後,可以通過
hap -V
檢視是否安裝成功,成功的話會輸出0.0.26
類似版本號。
到這裡恭喜你完成了環境搭建。
2.2 建立HelloWorld
選擇一個合適的資料夾,輸入:
hap init <ProjectName >
為你的專案名稱。
完成後會顯示:
prompt: Init your Project: (helloworld)
繼續輸入你的專案命名的目錄名稱,別傻傻等著。
然後等待建立完畢。
可以看到:
然後,切到helloword目錄,執行命令列:
npm install
執行如下命令安裝依賴包(webpack,babel等)。
再執行:
npm run build
即可在dist目錄下生成rpk包。
官網提示:如果報錯遇到Cannot find module ‘…/webpack.config.js’,請重新執行一次hap update –force。這是由於高版本的npm在npm install時,會校驗並刪除了node_modules下部分資料夾,導致報錯。而hap update –force會重新複製hap-toolkit資料夾到node_modules中
有了rpk包之後,你肯定要想怎麼安裝呀!!!
2.3 安裝生成的包
你需要安裝:
2.3.1 手機安裝偵錯程式
點選後是個apk,安裝到手機上:
你會發現,你安裝上之後,什麼也幹不了,顏色都是灰的。很正常,你還需要安裝一個平臺。
如果你發現你按鈕都可以點選,那麼忽略下面的安裝平臺步驟。
2.3.2 手機安裝平臺預覽版
別擔心,依賴是個apk。
安裝完成後是:
你安裝完成後應該是個白板,啥也沒有,正常。
此時,你回到之前的安裝偵錯程式apk,會發現按鈕都可以點選了。
2.3.3 第一次安裝
還記得剛才helloworld生成的rpk包麼,可以
adb push xxx.rpk /sdacrd/
push到手機根目錄,然後選擇本地安裝,選擇rpk包即可。
你還可以…選擇掃碼安裝,不過我沒成功,自己參考官網咖。
安裝完成後是這個樣子:
到這裡,恭喜你已經開發了第一個塊應用了~
你可以開啟佈局邊界看看是否是原生的。
三、自己開發一個快應用
3.1 基礎配置
想要自己開發一個快應用,首先應該有個IDE來用。
你可以選擇webstorm,vscode,或者sublime,當然如果你都沒有,用記事本吧…
我這裡使用的是vscode,不過和sublime體驗差不多…
首先我們修改src/manifest.json:
修改下logLevel為debug,這個很關鍵,一會看不見日誌會很痛苦。
然後我們修改了包名,應用名和icon,這些無所謂.
此時你可以執行:
npm run build
然後就會生成新的rpk檔案了,接下來安裝。
3.2 文章列表頁
我們直接用他的Demo/index.ux
3.2.1
先編寫一下佈局,佈局為一個list和一個上拉載入元件:
<template>
<list class="main-page" onscrollbottom="loadMoreData">
<block for="articleList">
<list-item type="article-item" class="article-item" onclick="loadUrl($item.link)">
<text class="title">{{$item.title}}</text>
<div style="display:flex;flex-direction:row;margin-top:12px;">
<text class="author">{{$item.author}}</text>
<text class="date">{{$item.niceDate}}</text>
</div>
</list-item>
</block>
<list-item type="loadStatus" class="load-status" style=" justify-content: center;padding:20px;">
<progress type="circular" show="{{hasMoreData}}"></progress>
<text show="{{hasMoreData}}">載入更多</text>
<text show="{{!hasMoreData}}">沒有更多了~</text>
</list-item>
</list>
</template>
大致說一下,list標籤設定了一個onscrollbottom,即滾動到底部會觸發loadMoreData.
渲染會遍歷讀取articleList陣列,然後通過{{$item.title}}的方式取單個物件的屬性值,此例為取title屬性。
我們還給list-item加了一個onclick時間,觸發loadUrl.
3.2.2 編寫js
編寫JS
<script>
import webview from '@system.webview'
import router from '@system.router'
var url = 'http://www.wanandroid.com/article/list/$pageId/json';
export default {
data: {
title: '文章列表',
articleList: [],
hasMoreData: true,
// 每次渲染的商品數
size: 20,
// 是否正在fetch請求資料
isLoadingData: false,
curPage: 0
},
onInit() {
this.$page.setTitleBar({ text: '文章列表' }),
this.loadArticlesJson();
},
async loadArticlesJson() {
// 成功示例
const ret1 = await natives.fetch({
url: 'http://www.wanandroid.com/article/list/0/json',
})
console.info('fetch成功結果: ', JSON.stringify(ret1));
var returnCode = ret1.data.code ;
if(returnCode == 200){
var articlesJson = JSON.parse(ret1.data.data);
this.articleList = this.articleList.concat(articlesJson.data.datas);
}else{
// failed !!!
console.error('load article list failed!');
}
},
async loadMoreData() {
if (this.isLoadingData) {
return;
}
this.isLoadingData = true;
this.curPage = this.curPage + 1;
console.info("loadurl ", url.replace("$pageId", this.curPage));
const ret1 = await natives.fetch({
url: url
})
var articlesJson = JSON.parse(ret1.data.data);
this.articleList = this.articleList.concat(articlesJson.data.datas);
this.isLoadingData = false;
},
loadUrl(url) {
webview.loadUrl({
url: url
});
}
}
</script>
data中定義了一些資料結構,當發生修改時會觸發渲染。
在onInit的時候我們設定了標題,並呼叫了this.loadArticlesJson方法,這裡會直接去訪問:
訪問json資料,然後我們加入到this.articleList中渲染介面。
當拉到底部時,會觸發loadMoreData,一樣是載入資料並渲染。
當點選單個條目時,觸發loadUrl,即通過webview去載入頁面。
此時你還不能執行,因為使用了
await natives
去訪問,還需要一些配置。
來到src/app.ux設定一些全域性配置,在裡面新增:
// 指令碼:regenerator.js
// 全域性引用
const globalRef = global.__proto__ || global
// global注入regeneratorRuntime
globalRef.regeneratorRuntime = require('babel-runtime/regenerator')
// asyncNatives.js
import nativeFetch from '@system.fetch'
const natives = {
/**
* 網路請求
* @param options
* @return {Promise}
*/
async fetch (options) {
const p1 = new Promise((resolve, reject) => {
options.success = function (data, code) {
resolve({ data, code })
}
options.fail = function (data, code) {
resolve({ data, code })
}
nativeFetch.fetch(options)
})
return p1
}
}
globalRef.natives = natives
即可。
當然執行過程中,最好開啟日誌檢視,可以開啟一個命令列,執行:
adb logcat | grep JsConsole
即可看到每個頁面建立、啟動、銷燬等日誌。
你也可以在AS的logcat中檢視。
你在寫程式碼時,也可以通過console.info()
列印日誌。
到這裡,一個入門教程就完畢了,你可以打包、安裝看效果了。
四、最後
這只是個入門教程,用於激發你的興趣。
如果想要更好的開發:
- 務必仔細讀官方文件,瞭解各種配置,頁面生命週期,各種元件等;
- 好好學習flex佈局,講道理我們Android也有;
- 需要學習下js,以及其渲染頁面機制
- 還需要良好的耐心…
總體而言和小程式類似,學習成本沒那麼高,如果需要,管他呢,反正咱也學得會~