編輯:關於Android編程
那麼Activity以哪種啟動模式進行跳轉時,會導致目標Activity獲取不到傳遞過來的數據呢?在上一篇博客中講到Activity以不同的啟動模式進行啟動會根據啟動模式來創建相應的實例,也就是說,如果目標Activity的實例已經存在並且符合要求,則不會再創建相應的實例,因此在Activity的4種啟動模式中,以singleTop(有可能)、singleTask、singleInstance模式啟動的目標Activity,當置於後台被再次啟動時都會導致目標Activity獲取不到傳遞過來的數據(這裡指的獲取不到是指在不借助其它操作時)。
這裡以singleTop模式來講解,當在StandardActivity中點擊SingleTopActivity按鈕時,會將輸入的內容或者默認的內容通過Intent傳遞給目標SingleTopActivity然後獲取並顯示出來,主要代碼代碼如下所示:
public void skip2SingleTopActivity(View view){ Intent intent = new Intent(StandardActivity.this,SingleTopActivity.class); content = et_content.getText().toString().trim(); if(TextUtils.isEmpty(content)){ content = "這是從StandardActivity傳遞過來的內容"; } intent.putExtra(SingleTopActivity.SINGLE_TOP,content); startActivity(intent); }目標SingleTopActivity獲取並顯示數據的代碼如下所示:
private void getBundleData() { Log.i(TAG, "getBundleData"); Intent intent = getIntent(); if (intent != null) { result = intent.getStringExtra(SINGLE_TOP); tv_content.setText("結果為:" + result); } }其中getBundleData方法是在onCreate方法中調用的,點擊後的結果如下所示:
可以看到目標SingleTopActivity可以成功獲取傳遞過來的數據,現在重點來了,如果此時在SingleTopActivity中的EditText中輸入內容或者直接點擊SingleTopActivity按鈕讓它繼續跳轉到自己會出現什麼情況呢?
跳轉的主要代碼如下所示:
public void skip2SingleTopActivity(View view) { Intent intent = new Intent(SingleTopActivity.this, SingleTopActivity.class); String content = et_content.getText().toString().trim(); if (TextUtils.isEmpty(content)) { content = "這是從SingleTopActivity傳遞過來的數據"; } intent.putExtra(SINGLE_TOP, content); startActivity(intent); }此時SingleTopActivity中顯示的數據依然是從StandardActivity中傳過來的數據:
Intent對象大致包含Component、Action、Category、Data、Type、Extra和Flag這7種屬性,其中Intent的Flag屬性用於為該Intent添加一些額外的控制旗標,可以通過Intent的addFlags方法為Intent添加控制旗標。
其中常見的跟Activity跳轉有關的Flag旗桿有如下幾個:
1、FLAG_ACTIVITY_BROUGHT_TO_FRONT:經測試發現以該旗標啟動的目標Activity跟以旗標FLAG_ACTIVITY_NEW_TASK啟動的目標Activity一樣都會創建新的Activity實例。
2、FLAG_ACTIVITY_CLEAR_TOP:見名知意:清除當前Activity之上的所有實例,該Flag相當於Activity啟動模式中的singleTask,例如,一個Activity棧中包含有A、B、C、D ,4個Activity實例,當在Activity D中以該旗標啟動Activity B時,此時Activity棧中只包含A、B兩個Activity實例。
在ActivityD中以FLAG_ACTIVITY_CLEAR_TOP標志啟動之前:
在ActivityD中以FLAG_ACTIVITY_CLEAR_TOP標志啟動之後:
3、FLAG_ACTIVITY_NEW_TASK:默認啟動旗標,該旗標控制創建一個新的Activity實例,該Flag相當於Activity啟動模式中的standard。
4、FLAG_ACTIVITY_SINGLE_TOP:從名字中不難看出該Flag相當於Activity加載模式中的singleTop模式,即原來Activity棧中有A、B、C、D這4個Activity實例,當在Activity D中再次啟動Activity D時,Activity棧中依然還是A、B、C、D這4個Activity實例。
5、FLAG_ACTIVITY_NO_HISTORY:如名字沒有歷史Activity一樣,以該旗標啟動的Activity不會保留在Activity棧中,如:Activity棧中有A、B兩個Activity實例,當在Activity B中以該旗標啟動Activity C,在Activity C中再啟動Activity D,此時Activity棧中只有A、B、D三個Activity實例,即Activity C不會保留在Activity棧中。
當然也可以通過在Activity D中以FLAG_ACTIVITY_CLEAR_TOP旗標的方式啟動Activity C,如果Activity C還保留在Activity棧中的話,那麼此時棧中的肯定只有A、B、C這三個Activity的實例,但是實踐證明Activity棧中有A、B、D、C這四個實例,也就進一步說明在Activity B中以FLAG_ACTIVITY_NO_HISTORY旗標啟動Activity C,再在Activity C中啟動Activity D後,Activity C不會在保留在Activity棧中,所以才會出現當在Activity D中以FLAG_ACTIVITY_CLEAR_TOP旗標的方式啟動Activity C時會創建新的Activity C實例,棧中情況如下所示:
6、FLAG_ACTIVITY_REORDER_TO_FRONT:即如果棧中已有該Activity則直接將該Activity帶到前台。如:Activity棧中有A、B、C、D四個Activity,如果在Activity D使用該旗標啟動Activity C,那麼啟動後Activity棧中的情形為:A-B-D-C。
啟動前Activity棧中的情況:
啟動後Activity棧中的情況:
從原因一:Activity的啟動模式中可以發現,如果Activity棧中已經存在目標Activity的實例的話,當從後台再次返回到Activity的棧頂時都有可能導致目標Activity獲取不到傳遞過來的數據,同樣的,原因二:Intent設置的Flag屬性如果也會讓目標Activity的實例保留在Activity棧中且滿足條件的話當再次啟動時也會導致目標Activity獲取不到傳遞過來的數據,這裡本來也將會通過以Activity的singleTop啟動模式相對應的FLAG_ACTIVITY_SINGLE_TOP旗標來講解的,不過由於篇幅原因,所以打消了這種想法,如果真有需要的話,可以去下載源碼查看。
知道原因之後,那麼該如何解決這個問題呢?其實谷歌早就考慮到了這種問題,於是在Android api中的Activity類中給我們提供了一個叫onNewIntent的方法來解決這個問題:
當一個Activity的啟動模式是singleTop或者使用FLAG_ACTIVITY_SINGLE_TOP這個標記啟動的時候,並且Activity的棧頂就是待啟動的目標Activity的時候,會調用目標Activity的這個方法,如果需要在後續的目標Activity的生命周期中可以獲取最新的數據,可以在該方法中通過setIntent方法更新數據。(ps:不完全是按照翻譯)
知道了解決辦法以後,在目標SingleTopActivity重寫onNewIntent方法並在該方法中通過setIntent方法來更新數據以確保在目標SingleTopActivity後續的生命周期中可以獲取最新的數據,主要代碼如下所示:
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (intent != null) { result = intent.getStringExtra(SINGLE_TOP); Log.e(TAG, "onNewIntent result==" + result); setIntent(intent); } } @Override protected void onResume() { super.onResume(); Log.e(TAG, "onResume"); Intent intent = getIntent(); if (intent != null) { result = intent.getStringExtra(SINGLE_TOP); tv_content.setText("結果為:" + result); } }此時,輸入內容並點擊SingleTopActivity按鈕可以發現已經可以獲取最新的數據了,結果如下所示:
Log日志如下所示:
至此,Activity啟動模式及Intent的Flag屬性對Intent傳值的影響就介紹完了。
另外,為了方便開發,很多公司都會封裝一些常用的工具類,如:為了減少Activity實例的的創建,會對Activity的跳轉進行一系列的封裝的IntentUtils工具類中往往會給Intent添加addFlags方法以減少實例的創建,因此小伙伴們在使用自己公司封裝好的工具類時需要時刻留意。
1. 測試相關概念1.1. 測試的分類按照是否知道源代碼:1.黑盒測試:不知道源代碼2.白盒測試:知道源代碼按照測試的粒度:1.方法測試 function test2.單
相信很多開發者會把圖片存放到七牛上,我的web站點也是吧圖片存儲到七牛上,對於以圖片為主的站點,這樣可以節省很大帶寬。將圖片上傳到七牛服務器的重點就是獲得上傳憑證uplo
最近項目做完了,有閒暇時間,一直想做一個類似微信中微信發說說,既能實現拍照,選圖庫,多圖案上傳的案例,目前好多App都有類似微信朋友圈的功能,能過發表說說等附帶圖片上傳。
Android控件監聽方面,用接口實現監聽是最好的,在Android 本身就提供了各種控件監聽接口,我們只要按照這樣實現,看起來代碼會很整潔。實現的效果也是很