Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android]startActivityForResult啟動singleTask的Activity,則onActivitResult()立即回調且resultCode為RESULT_CANCEL

[Android]startActivityForResult啟動singleTask的Activity,則onActivitResult()立即回調且resultCode為RESULT_CANCEL

編輯:關於Android編程

問題現象:

在剛安裝完demo應用未登錄任何帳號時,通過系統內的分享功能想將文件/圖片等內容"發送給好友"或"發送到我的電腦",觸發登錄界面,但登錄成功後,沒有跳轉到選擇demo好友發送界面,無法繼續發送。

本文為Sodino所有,轉載請注明出處:http://blog.csdn.net/sodino/article/details/22101881

代碼分析:

demo中JumpActivity處理著各種外部應用分享入口,通過調試發現進行分享時會判斷是否登錄過,如果未登錄則會跳轉至LoginActivity進行登錄。如下代碼:

        
         private void doShare(booleancheckLogin) {
                   // 系統級分享
                   Intent intent = getIntent();
                   ... ...
                   ... ...
                  
                   // 沒登錄
                   if (checkLogin &&!demo.isLogin()){
                            Intent i = newIntent(this, LoginActivity.class);
                            i.putExtra("isActionSend",true);
                            i.putExtras(extra);
                            i.putExtras(i);
                            startActivityForResult(i,SHARE_LOGIN_REQUEST);
                            return;
                   }
                   ... ...
         }

查閱代碼得知登錄成功後,則JumpActivity.onActivityResult()將會得到requestCode值為SHARE_LOGIN_REQUEST的回調。為此,在onActivityResult()回調處設置斷點,再次跟進。

設置斷點,執行分享操作進行調試,發現每次執行完startActivityForResult(),則onActivityResult()便立刻被回調了,且resultCode值為RESULT_CANCEL。至些,問題開始有了頭緒。

通過排查,發現LoginActivity在之前有被改動過,其launchMode賦值為singleTask。分享功能就是在這次改動之後失效了的。只要恢復launchMode為standard,即可讓onActivityResult()在LoginActivity登錄成功後正常回調回來,執行分享操作,恢復功能。

至此,問題得到解決,但問題原因仍是一頭霧水:

為什麼通過startActivityForResult()方式去啟動launchMode=singleTask的Activity,onActivityResult()會被立即回調且resultCode值為RESULT_CANCEL??

原因解析:

經查文檔,發現文檔中另一相似的方法startActivityForResult(Intent,int,Bundle)有說明如下:

Note that this method should only be used with Intent protocols thatare defined to return a result. In other protocols (such as ACTION_MAIN orACTION_VIEW), you may not get the result when you expect. For example,if the activity you are launching uses thesingleTask launch mode, it will not run in your task and thus you willimmediately receive a cancel result.

但這點注釋讓人理解得仍不是很透徹。繼續搜索,發現文檔(點擊這裡)裡說了下面的這一種現象。

在下圖中,存在著前兩個棧,其中直接顯示在屏幕上與用戶交互的Back Stack,及另一個隱藏在後台的Background Task,該棧棧頂的Activity Y其launchMode為singleTask

如果在Activity 2中調用BackgroundTask中已經啟動過的Activity Y,則Background Task內占據屏幕並且該Task下所有的棧都會保留當前的棧位置及順序push進Back Task形成新的結構,順序由上至下為Activity Y→Activity X→Activity 2→Activity 1。

在Activity Y界面按返回鍵,則ActivityY出棧,Activity X占據屏幕!注意,由Activity2調用的Activity Y,但返回鍵後,回退顯示的是Activity X!所以即使在Activity Y執行setResult(),Activity 2也是無法接收到的。換回文章開頭的問題,即在JumpActivity處啟動LoginActivity(已經被設置singleTask了),則LoginActivity的setResult()結果有可能不會傳給JumpActivity。

繼續按返回鍵,則才回到Activity 2。

問題結論:

由此,我們再回到先前的問題。在這種Tasks的入棧與出棧設計下,由於可能有Activity X的存在,所以在Activity 2啟動Activity Y時,則直接回調了onActivityResult()並給出了RESULT_CANCEL也就可以理解了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved