成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

看我用Android開發者聽得懂的語言解釋快應用頁面的生命周期和接口router-12.4

開發
就像世界上第一批Android工程師大多都是iOS工程師轉行一樣,世界上第一批QuickApp工程師也大多都是Android工程師轉行。

就像世界上***批Android工程師大多都是iOS工程師轉行一樣,世界上***批QuickApp工程師也大多都是Android工程師轉行。將快應用知識與Android知識對比學習可以起到溫故知新的效果。

查閱快應用官方文檔可知快應用的“頁面”和Android原生的Activity都是提供一個可以給用戶來交互的屏幕,在底層也都是用Stack保存瀏覽記錄。理解頁面的生命周期就像理解Activity’的生命周期一樣,有助于更好的組織頁面的業務邏輯,方便頁面之間的交互與資源釋放等的處理。但為何“頁面”僅有三種狀態而Activity卻有四種呢?又為何“頁面”沒有類似Activity的啟動模式呢?本文將為你揭曉答案:

頁面的生命周期和狀態

眾所眾知Activity的生命周期由七個主要被動方法以及onBackPressed()、onNewIntent()、onActivityResult()、onSaveInstanceState()和onRestoreInstanceState()等其他被動方法組成,并且有、、和共四種狀態;而查閱官方文檔可知頁面的被動方法僅有七個,而狀態只有、和三種。我來給大家對比分析一下兩組方法的對應關系。

onInit()和onReady()

根據快應用官方文檔的說法:onInit()方法表示ViewModel的數據已經準備好,可以開始使用頁面中的數據,能且僅能調用一次。onReady()方法表示ViewModel的模板已經編譯完成,可以開始獲取DOM節點,能且僅能調用一次。

每個Android開發者的類庫里都有一個BaseActivity,這個BaseActivity里一般都有初始化配置、綁定View的同步方法onInitViews()和請求數據的異步方法onInitData();我們可以把onInit()理解為onInitData(),把onReady()理解為onInitViews()。

如果把眼光放遠一點,拿頁面與Fragment比較,onInit()更像Fragment的onCreate(),而onReady()更像onCreateView()。

onShow()和onHide()

每個快應用的App中可以同時運行多個頁面,但是每次只能顯示其中一個頁面;這點不同于Android開發,可以同時顯示多個Activity;也不同與純前端開發,瀏覽器頁面中每次只能有一個頁面,當前頁簽打開另一個頁面,上個頁面就銷毀了。

根據快應用官方文檔的說法:頁面被切換隱藏時調用onHide(),頁面被切換重新顯示時調用onShow()。很明顯這與Activity有onStart()和onStop()、onResume()和onPause()兩對方法不同,這是因為頁面不像Activity有透明背景和Theme.Dialog主題,所以Activity的可見狀態和前臺狀態在頁面里僅對應顯示狀態。

onDestroy()

根據快應用官方文檔的說法:onDestroy()方法在頁面被銷毀時調用,能且僅能調用一次。被銷毀的可能原因有:用戶從當前頁面返回到上一頁,或者用戶打開了太多的頁面,框架自動銷毀掉部分頁面,避免占用資源。而官方建議頁面進入銷毀狀態時應該做一些釋放資源的操作,這和Activity的onDestroy()方法的推薦使用方式不謀而合,所以頁面的onDestroy()方法就是Activity的onDestroy()方法。

onBackPress()

根據快應用官方文檔的說法:當用戶點擊實體BACK按鍵或左上角返回菜單時觸發onBackPress()事件。我想沒有人不會把頁面的onBackPress()方法和Actvity的onBackPressed()方法聯系到一起。

如果事件響應方法***返回true表示不返回,自己處理業務邏輯,完畢后開發者自行調用router.back()方法返回。代碼如下:


onBackPress (params) {

//做自己喜歡的事

return true

}

對比一下Activity的onBackPressed()的override方式:


@Override 

public void onBackPressed() { 

// super.onBackPressed();

// 做自己喜歡的事 

}

onMenuPress()

對比一下onBackPress()可知:當用戶點擊右上角菜單時觸發onMenuPress()事件。如果我們有使用菜單的需求,可以通過manifest.json中的menu屬性配置是否顯示右上角的菜單。

所有支持快應用的國產Android設備的MENU鍵都用來清理內存,因此實體MENU鍵不會觸發onMenuPress(),這點與onBackPress()有所區別。

頁面路由接口router

根據快應用官方文檔的說法:我們可以通過配置a組件的href屬性跳轉到應用內的頁面,有點類似于Android開發中已不被推薦使用的的隱式Intent跳轉Activity;此外我們也可以使用router接口,這就有點類似于Android開發的顯式Intent組件或者ARouter框架。本文的一切頁面跳轉都使用router接口。

常見方法

接口router常見方法在官方文檔里寫得很清楚,我只講幾點注意事項:

(1)接口router的push()方法能跳轉應用外的Activity包括電話、短信、郵件和其他快應用

(2)接口router的push()方法不能實現Android的Intent的“android.intent.category.HOME”標簽的功能,也就是說,除非用戶點HOME能回到桌面,否則開發者不能靠重寫onBackPress()保留首頁

(3)打開照相機、QQ聊天、微信分享、支付寶付款用的不是router

(4)back()方法的路徑參數是path,并非push()和replace()的uri

回傳參數的方式

傳遞參數的方式不在本文的討論范圍之內,但回傳參數的方式卻涉及生命周期,我們先看快應用回傳參數的官方代碼:


onHide () {

// 頁面被切換隱藏時,將要傳遞的數據對象寫入全局變量

this.$app.$data.dataPageB = {

gotoPage: 'pageA',

params: {

msg: this.msg

}

}

},

對比一下Activity的setResult()方法的調用:


Intent intent = new Intent(); 

intent.putExtra("dataPageB",dataPageB); 

setResult(RESULT_OK,intent);

快應用接收回傳參數的官方代碼:

 

onShow () {

// 頁面被切換顯示時,從數據中檢查是否有頁面B傳遞來的數據

if (this.$app.$data.dataPageB && this.$app.$data.dataPageB.gotoPage === 'pageA') {

// 從數據中獲取回傳給本頁面的數據

const data = this.$app.$data.dataPageB.params

this.msg = data.msg

}

},

對比一下Activity的onActivityResult()方法:

 

@Override 

protected void onActivityResult(int requestCode, int resultCode, Intent data) { 

super.onActivityResult(requestCode, resultCode, data); 

if (requestCode == pageA && resultCode == RESULT_OK){ 

this.msg = ((BaseBean)data.getSerializableExtra("dataPageB")).getMessage(); 

} 

}

由此可見,在onRscume()方法里檢驗全局變量的變化這一行為,作為Android原生開發中飽受詬病的新手行為,在快應用開發中是官方推薦的,所以快應用不需要類似onActivityResult()方法的方法。

研究接口router和頁面生命周期關系的實踐

“紙上得來終覺淺”,我們寫一個LifecycleDemo來研究接口router和頁面生命周期關系:

首先打開這個LifecycleDemo,我們可以看到logcat打印出如下信息:

 

### 頁面A onInit ###

### 頁面A onReady ###

### 頁面A onShow ###

當前頁面在頁面棧中的位置 : 1/1

點擊BACK鍵,返回桌面,logcat打印出如下信息:

 

### 頁面A onBackPress ###

### 頁面A onHide ###

### 頁面A onDestroy ###

與官方文檔描述相同,符合預期

打開其他Activity

接下來我們打開其他Activity,包括系統桌面、打電話界面和其他應用

點擊HOME鍵,然后熱啟動LifecycleDemo,Logcat打印如下:


### 頁面A onHide ###

### 頁面A onShow ###

當前頁面在頁面棧中的位置 : 1/1

應用內打開其他系統Activity,然后熱啟動LifecycleDemo,Logcat打印如下:


### 頁面A onHide ###

### 頁面A onShow ###

當前頁面在頁面棧中的位置 : 1/1

應用內打開別的快應用,然后熱啟動LifecycleDemo,Logcat打印如下:

### 頁面A onHide ###

### 頁面A onShow ###

當前頁面在頁面棧中的位置 : 1/1

結論:符合預期,支持上文onShow()相當于onStart()和onResume(),onHide()相當于onPause()和onStop()的猜想。

用push()方法進行應用內頁面跳轉

用push()方法跳轉到頁面A,logcat打印如下:


### 頁面A onHide ###

### 頁面A onInit ###

### 頁面A onReady ###

### 頁面A onShow ###

當前頁面在頁面棧中的位置 : 2/2

顯然頁面棧里的順序為AA,支持上文頁面的啟動模式相當于Activity的Standard模式的猜想。現在猜想***個A是前面的,第2、3、4個A是后面的。我們接著用push()方法跳轉到頁面B,logcat打印如下:


### 頁面A onHide ###

### 頁面B onInit ###

### 頁面B onReady ###

### 頁面B onShow ###

當前頁面在頁面棧中的位置 : 3/3

顯然頁面棧里的順序為AAB,也符合預期,支持上文猜想。

我們發現快應用官方文檔存在歧義,就是首頁究竟是指穩定運行時頁面棧底的頁面(類似Android原生開發的MainActivity),還是指manifest.json文件中“router.entry”對應的頁面(類似AndroidManifest.xml文件中帶“android.intent.action.MAIN"標簽的Activity,通常被命名為SplashActivity),我們驗證一下:

當“router.entry”對應頁面A,而頁面棧里頁面順序為BBAACC的時候,我們用push()方法跳轉到首頁。首頁是這樣的:

而logcat打印如下:

### 頁面C onHide ###

### 頁面A onInit ###

### 頁面A onReady ###

### 頁面A onShow ###

當前頁面在頁面棧中的位置 : 7/7

原來接口router可以跳轉的首頁指的是“router.entry”對應的頁面。

用replace()方法進行應用內頁面跳轉

當頁面棧里僅有A的情況下,用replace()方法跳轉到頁面A,logcat打印如下:

### 頁面A onHide ###

### 頁面A onDestroy ###

### 頁面A onInit ###

### 頁面A onReady ###

### 頁面A onShow ###

當前頁面在頁面棧中的位置 : 1/1

顯然頁面棧里僅有一個A,猜想replace()方法類似Activity里的這段代碼:

 


startActivity(intent);

finish();

又猜想第1、2個A是前面的,第3、4、5個A是后面的。我們接著用replace()方法跳轉到頁面B,logcat打印如下:

 

### 頁面A onHide ###

### 頁面A onDestroy ###

### 頁面B onInit ###

### 頁面B onReady ###

### 頁面B onShow ###

當前頁面在頁面棧中的位置 : 1/1

符合預期,支持上文猜想。

用back()方法進行應用內頁面跳轉

在頁面棧里的順序為AABBCC的情況下,根據文檔僅能得出用back()方法返回上一頁后頁面棧里的順序為AABBC,返回頁面B后頁面棧里的順序為AABB,返回頁面A或首頁后頁面棧里的順序為AA,有點類似Intent的FLAG_ACTIVITY_CLEAR_TASK標簽。我們只討論官方文檔忽略的內容:

我們用back()方法跳轉到頁面C,頁面無變化;在頁面棧里的順序為ABCABC的情況下,我們用back()方法跳轉到頁面C,頁面也無變化。得出back()方法不能用來跳轉到棧頂頁面的結論。

總結

本文中獲得的有關快應用頁面生命周期的知識和經驗的總結如下:

(1)頁面可以理解為Activity,并且啟動模式能且僅能為standard

(2)頁面的onInit()和onReady()可以分別理解為你的BaseActivity的onInitData()和 onInitViews()。

(3)Activity的可見狀態和前臺狀態在頁面里都是顯示狀態,所以onShow()可以理解為onStart()和onResume(),同理onHide()可以理解為onPause()和onStop()

(4)頁面的onDestroy()里可以理解為Activity的onDestroy()

(5)快應用沒有singleTop這種啟動模式,自然沒有onNewIntent()方法,但用replace()方法啟動棧頂頁面可以起到同樣效果。

(6)onActivityResult()、onSaveInstanceState()和onRestoreInstanceState()和也都沒有對應方法

(7)onBackPress()是BACK鍵觸發的方法,可以被攔截,但無法改成HOME鍵的效果

(8)onMenuPress()方法不是MENU鍵觸發的方法

(9)快應用沒有singleTask這種啟動模式,但back()方法起到類似Intent的FLAG_ACTIVITY_CLEAR_TASK的作用。

(10)back()方法不能用來跳轉到棧頂頁面。

(11)官方文檔中所有的“首頁”都指manifest.json文件中“router.entry”對應的頁面(類似AndroidManifest.xml文件中帶“android.intent.action.MAIN"標簽的Activity,通常被命名為SplashActivity),而不是指指穩定運行時頁面棧底的頁面(類似Android原生開發的MainActivity)

附錄:本文完整代碼

頁面A(文件路徑:…/src/PageA/index.ux)的完整代碼(B、C的代碼僅title不同):

<template>

<div class="doc-page">

<text class="title">歡迎打開{{title}}</text>

<text class='text' if="{msg}">{{msg}}</text>

<input type="button" class="btn" onclick="this.$app.$def.routePush('/PageA')" value="用push()方法跳轉到頁面A" />

<input type="button" class="btn" onclick="this.$app.$def.routePush('/PageB')" value="用push()方法跳轉到頁面B" />

<input type="button" class="btn" onclick="this.$app.$def.routePush('/PageC')" value="用push()方法跳轉到頁面C" />

<input type="button" class="btn" onclick="this.$app.$def.routePush('/')" value="用push()方法跳轉到首頁" />

<input type="button" class="btn" onclick="this.$app.$def.routeReplace('/PageA')" value="用replace()方法跳轉到頁面A" />

<input type="button" class="btn" onclick="this.$app.$def.routeReplace('/PageB')" value="用replace()方法跳轉到頁面B" />

<input type="button" class="btn" onclick="this.$app.$def.routeReplace('/PageC')" value="用replace()方法跳轉到頁面C" />

<input type="button" class="btn" onclick="this.$app.$def.routeReplace('/')" value="用replace()方法跳轉到首頁" />

<input type="button" class="btn" onclick="this.$app.$def.routeBack('/PageA')" value="用back()方法跳轉到頁面A" />

<input type="button" class="btn" onclick="this.$app.$def.routeBack('/PageB')" value="用back()方法跳轉到頁面B" />

<input type="button" class="btn" onclick="this.$app.$def.routeBack('/PageC')" value="用back()方法跳轉到頁面C" />

<input type="button" class="btn" onclick="this.$app.$def.routeBack('/')" value="用back()方法跳轉到首頁" />

<input type="button" class="btn" onclick="this.$app.$def.routeBack()" value="用back()方法返回上一頁" />

 

<input type="button" class="btn" onclick="routeClear()" value="只保留當前頁面" />

<input type="button" class="btn" onclick="this.$app.$def.routePush('tel:10086')" value="跳轉到打電話頁面" />

<input type="button" class="btn" onclick="this.$app.$def.routePush('hap://app/me.ele.xyy/')" value="跳轉到指定快應用(餓了么)" />

</div>

</template>

<style>

@import '../Common/css/common.css';

.title {

font-size: 40px;

text-align: center;

}

.text {

font-size: 30px;

text-align: center;

}

</style>

<script>

import router from '@system.router'

export default {

private: {

msg:'',

title: '頁面A',

},onInit () {

this.$page.setTitleBar({text: this.title})

console.error(`### `+this.title+` onInit ###`)

this.msg = ""

},

onReady () {

console.error(`### `+this.title+` onReady ###`)

},

onShow () {

console.error(`### `+this.title+` onShow ###`)

this.msg = this.$app.$def.routeInfo()

console.error(`${this.msg}`)

},

onHide () {

console.error(`### `+this.title+` onHide ###`)

},

onDestroy () {

console.error(`### `+this.title+` onDestroy ###`)

},

onBackPress (params) {

console.error(`### `+this.title+` onBackPress ###`)

},

onMenuPress () {

console.error(`### `+this.title+` onMenuPress ###`)

},

routeClear() {

this.$app.$def.routeClear()

 

this.msg = this.$app.$def.routeInfo()

console.error(`${this.msg}`)

}

 

}

</script>

工具類util.js的完整代碼:

import router from '@system.router' 
 
function routePush(uri,params) { 
 
// 跳轉到應用內的某個頁面,或其他Activity 
 
// 匹配到與路徑與uri相同的頁面,則跳轉到該頁面,否則跳轉到首頁 
 
// 參數為"/",跳轉到首頁 
 
// uri若為包含schema的完整uri,則跳轉到應用外的Activity(目前僅支持電話、短信、郵件和其他快應用) 
 
// params為傳遞的參數,不在本文討論范圍內 
 
router.push ({ 
 
uri: uri, 
 
params: params 
 
}) 
 
} 
 
function routeReplace(uri,params) { 
 
// 跳轉到應用內的某個頁面,同時關閉當前頁面 
 
// 除了不能跳轉到應用外的頁面,一切同push()方法 
 
router.replace ({ 
 
uri: uri, 
 
params: params 
 
}) 
 
} 
 
function routeBack(path) { 
 
// 跳轉到應用內的某個已經打開過的頁面,同時關閉當前頁面 
 
// 不傳參數,或沒有匹配到對應頁面,則返回上一個頁面 
 
// 參數為"/",返回首頁 
 
// 若匹配到多個頁面,返回至***打開的頁面 
 
// 注意back()方法的參數是path而不是uri 
 
router.back ({ 
 
path: path 
 
}) 
 
} 
 
function routeInfo (){ 
 
// 用getState()方法獲取當前頁面狀態,index表示當前頁面在頁面棧中的位置(計數從0開始) 
 
// 用getLength()方法獲取當前頁面棧的頁面數量 
 
return `當前頁面在頁面棧中的位置 : `+ (router.getState().index + 1) + `/` + router.getLength() 
 
} 
 
function routeClear (){ 
 
// 清空所有歷史頁面記錄,僅保留當前頁面 
 
router.clear() 
 
} 
 
export default { 
 
routeReplace, 
 
routePush, 
 
routeBack, 
 
routeInfo, 
 
routeClear 
 
} 

 

責任編輯:張燕妮 來源: 51CTO
相關推薦

2019-07-18 13:01:18

數據科學數據湖數據挖掘

2015-10-16 09:19:12

2022-04-19 07:20:24

軟件開發安全生命周期SSDLC應用安全

2012-06-20 10:29:16

敏捷開發

2013-07-29 05:11:38

iOS開發iOS開發學習類的'生命周期'

2011-06-16 09:31:21

ActivityAndroid

2015-07-09 15:42:48

ios應用生命周期

2014-07-16 13:39:30

Windows Pho

2009-06-24 10:34:39

JSF生命周期JSF應用程序

2015-07-08 16:28:23

weak生命周期

2013-04-07 10:42:56

Asp.Net頁面周期

2018-10-29 10:08:01

2022-09-27 17:27:05

Windchill+SaaSPTC

2014-07-11 11:09:10

App應用程序生命周期

2023-05-18 10:48:29

Linux操作系統

2012-08-16 09:38:38

ASP.NET

2012-12-04 10:02:03

2013-07-31 14:50:32

Windows PhoWP應用程序生命周期

2009-08-04 16:05:15

ASP.NET頁面生命

2009-08-04 16:50:15

ASP.NET頁面生命
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩在线不卡 | 五月天激情电影 | 伊人狠狠| 免费一级大片 | 成年人视频在线免费观看 | www.99热.com| 谁有毛片 | 人人操日日干 | 一区二区成人 | 久久亚洲天堂 | 国产91视频免费 | 亚洲欧美综合精品久久成人 | 久久久久久久久久一区二区 | 欧美午夜精品久久久久久浪潮 | 亚洲精品久久久久久一区二区 | 男人的天堂中文字幕 | 亚洲第一成人av | 日产久久| 成人黄色在线观看 | 亚洲最大成人综合 | 亚洲精品视频一区 | 亚洲成人精品在线观看 | www.久久.com| 国产精品成人一区二区三区 | 91久久国产 | 在线看片国产精品 | 成人小视频在线 | 天天干天天爽 | 成人av网站在线观看 | 色综合av | 欧美精品一区二区三区蜜桃视频 | 精品日韩在线 | 日韩一区不卡 | 欧美成人精品在线 | 日批日韩在线观看 | 国产在线视频一区 | 久久国产精品网 | 男女网站免费观看 | 我要看黄色录像一级片 | av资源中文在线 | 超碰成人免费 |