編輯:關於Android編程
最近在研究AMS代碼遇到一個問題,在函數startActivityUncheckedLocked中
Slog.d("DDY", "!!!!!!!!!!!!!!!!!!!" ); if (r.packageName != null) { // If the activity being launched is the same as the one currently // at the top, then we need to check if it should only be launched // once. Slog.d("DDY", "=====11" ); ActivityStack topStack = getFocusedStack(); ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop); if (top != null && r.resultTo == null) { Slog.d("DDY", "========------ " ); if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) { if (top.app != null && top.app.thread != null) { if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task); /// M: AMS log enhancement @{ if(!ActivityManagerService.IS_USER_BUILD) Slog.d(TAG, "ACT-AM_NEW_INTENT " + top + top.task); /// @} // For paranoia, make sure we have correctly // resumed the top activity. topStack.mLastPausedActivity = null; if (doResume) { resumeTopActivitiesLocked(); } ActivityOptions.abort(options); if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and // the client said not to do anything if that // is the case, so this is it! if (r.task == null) Slog.v(TAG, "startActivityUncheckedLocked: task left null", new RuntimeException("here").fillInStackTrace()); return ActivityManager.START_RETURN_INTENT_TO_CALLER; } top.deliverNewIntentLocked(callingUid, r.intent); if (r.task == null) Slog.v(TAG, "startActivityUncheckedLocked: task left null", new RuntimeException("here").fillInStackTrace()); return ActivityManager.START_DELIVERED_TO_TOP; } } } } } else { Slog.d("DDY", "+++++++++----- " ); if (r.resultTo != null) { r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho, r.requestCode, Activity.RESULT_CANCELED, null); } ActivityOptions.abort(options); if (r.task == null) Slog.v(TAG, "startActivityUncheckedLocked: task left null", new RuntimeException("here").fillInStackTrace()); return ActivityManager.START_CLASS_NOT_FOUND; } Slog.d("DDY", "=====22" );
ActivityStack topStack = getFocusedStack();
ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
這兩句的意思是獲取當前正在顯示的棧頂的Activity,
例如OtherActivity在棧頂。當前獲取的就是OtherActivity,也就是顯示在當前手機界面的Activity。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">
if (top != null && r.resultTo == null) {
Slog.d("DDY", "========------ " );
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
top代表當前正在顯示的Activity, r.resultTo :假如A Activity 通過startActivityForResult啟動B Activity,那麼r.resultTo就是接收返回結果的A Activity。
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) 意思當前正在顯示的Activity正是我們正要啟動的Activity,
if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { .......... top.deliverNewIntentLocked(callingUid, r.intent); 這裡判斷當前的啟動模式 為FLAG_ACTIVITY_SINGLE_TOP LAUNCH_SINGLE_TOP 就是 singleTop模式, LAUNCH_SINGLE_TASK 就是 singleTask 模式。 如果啟動模式為上面任何一種的話就會啟動deliverNewIntentLocked函數,這個函數主要作用就是調用Activity的onNewIntent函數。就是我們常說的app中的單實例Activity。只存在一個Activity,當我們在啟動這個Activity只是重載,並不啟動新的
singleTop:
當某Task中有A、B、C、D4個Activity時,如果D想再啟動一個D類型的Activity,那麼Task將是什麼樣子呢?在singleTop模式下,Task中仍然是A、B、C、D,只不過D的onNewIntent函數將被調用以處理這個新Intent,而在standard模式下,則Task將變成A、B、C、D、D,最後的D為新創建的D類型Activity對象。在singleTop這種模式下,只有目標Acitivity當前正好在棧頂時才有效,例如只有處於棧頂的D啟動時才有用,如果D啟動不處於棧頂的A、B、C等,則無效。
上面是有關singleTop簡單的介紹,大家有沒有想過一個問題。網上有人說startActivityForResult 可以使用singleTop 模式。這句話說得沒錯。這是有一定條件的那就是A Activity啟動 B Activity 可以使用。在B Activity 啟動 自己的時候就不可以使用。那B啟動自己 會有什麼效果呢??
package com.example.systemupdate; import java.io.File; import java.io.IOException; import android.content.Intent; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.RecoverySystem; import android.os.storage.StorageVolume; import com.android.internal.os.storage.ExternalStorageFormatter; import android.util.Log; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import android.view.View; import android.view.View.OnClickListener; public class MainActivity extends Activity { private TextView txt; private Button Btn; private Button Btn2; private ProgressDialog pd; private boolean pptv = false; private Context context; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTitle("我是MainActivity"); Btn = (Button)findViewById(R.id.btn); Btn2 = (Button)findViewById(R.id.btn2); Btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub startActivity(new Intent(MainActivity.this,OtherActivity.class)); } }); } }
這是主 Activity ,我們在主Activity (MainActivity ) 啟動 OtherActivity ,
OtherActivity 模式為singleTop 模式
OtherActivity 代碼:
package com.example.systemupdate; import java.io.File; import java.io.IOException; import android.content.Intent; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.RecoverySystem; import android.os.storage.StorageVolume; import com.android.internal.os.storage.ExternalStorageFormatter; import android.util.Log; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import android.view.View; import android.view.View.OnClickListener; public class OtherActivity extends Activity { public static int n =0; private TextView txt; private Button Btn; private Button Btn2; private ProgressDialog pd; private boolean pptv = false; private Context context; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); n = n+ 1; setTitle("我是OtherActivity" + n); Btn = (Button)findViewById(R.id.btn); Btn2 = (Button)findViewById(R.id.btn2); Btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub startActivity(new Intent(OtherActivity.this,OtherActivity.class)); } }); } protected void onNewIntent(Intent intent) { // TODO Auto-generated method stub super.onNewIntent(intent); Log.d("DDY", "OnNewIntent"); } }
再此情況下點擊 MainActivity的Btn2 啟動OtherActivity是可以正常啟動的此時顯示 “我是OtherActivity1”。OtherActivity的Btn2 啟動自己也是可以正常啟動。此時 會發現 界面仍是OtherActivity1,顯示我是“OtherActivity1”你不斷點擊OtherActivity1的Btn2 。界面仍是顯示我是“OtherActivity1”
此時打印日志會顯示
Log.d(“DDY”, “OnNewIntent”); 這句話被打印出來了。說明OtherActivity此時的啟動並不是新建OtherActivity,只是重載原來的OtherActivity。
D/DDY ( 5791): !!!!!!!!!!!!!!!!!!! D/DDY ( 5791): =====11 D/DDY ( 5791): ========------ D/DDY ( 6515): OnNewIntent
說明 函數 top.deliverNewIntentLocked(callingUid, r.intent)被調用了,由於此函數主要作用就是調用 onNewIntent 函數。所以 界面一直重載並不會新建OtherActivity。
現在考慮使用startActivityForResult 情況:
package com.example.systemupdate; import java.io.File; import java.io.IOException; import android.content.Intent; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.RecoverySystem; import android.os.storage.StorageVolume; import com.android.internal.os.storage.ExternalStorageFormatter; import android.util.Log; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import android.view.View; import android.view.View.OnClickListener; public class MainActivity extends Activity { final public int CODE= 0x717; public static int n =1; private TextView txt; private Button Btn; private Button Btn2; private ProgressDialog pd; private boolean pptv = false; private Context context; protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode==CODE && resultCode==CODE){ Log.e("DDY", "======================:"); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTitle("我是MainActivity"); Btn = (Button)findViewById(R.id.btn); Btn2 = (Button)findViewById(R.id.btn2); Btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub startActivityForResult(new Intent(MainActivity.this,OtherActivity.class),CODE); } }); } }
package com.example.systemupdate; import java.io.File; import java.io.IOException; import android.content.Intent; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.RecoverySystem; import android.os.storage.StorageVolume; import com.android.internal.os.storage.ExternalStorageFormatter; import android.util.Log; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import android.view.View; import android.view.View.OnClickListener; public class OtherActivity extends Activity { final public int CODE= 0x717; public static int n =1; private TextView txt; private Button Btn; private Button Btn2; private ProgressDialog pd; private boolean pptv = false; private Context context; protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode==CODE && resultCode==CODE){ Log.e("DDY", "======================:"); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); n = n+ 1; setTitle("我是OtherActivity" + n ); Btn = (Button)findViewById(R.id.btn); Btn2 = (Button)findViewById(R.id.btn2); Btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub startActivityForResult(new Intent(OtherActivity.this,OtherActivity.class),CODE); } }); } protected void onNewIntent(Intent intent) { // TODO Auto-generated method stub super.onNewIntent(intent); Log.d("DDY", "OnNewIntent"); } }
在這種情況下MainActivity的Btn2 啟動OtherActivity是可以正常啟動的此時顯示 “我是OtherActivity1”。
點擊返回鍵可以正常返回到MainActivity ,可以正常打印出
Log.e("DDY", "======================:");
D/DDY ( 5791): !!!!!!!!!!!!!!!!!!!
D/DDY ( 5791): =====11
D/DDY ( 5791): =====22
E/DDY ( 7156): ======================:
startActivityForResult 在 MainActivity 啟動OtherActivity 是起作用的。
如果OtherActivity 啟動自己,不斷點擊Btn2 ,發現 OtherActivity 不斷新建 OtherActivity ,並不會重載此時OtherActivity 顯示隨著點擊 不斷變化 “我是OtherActivity1” “我是OtherActivity2” “我是OtherActivity3” …….. 等等。
按返回鍵也可以 返回OtherActivity3 -> OtherActivity2 -> OtherActivity1 .說明此時的 singleTop 在 startActivityForResult 模式下面並沒有起作用。這個不起作用有條件的就是:
此時OtherActivity 正在棧頂且為singleTop 模式。並且用startActivityForResult 啟動 自己。此時的singleTop 不起作用。被當做standard 模式。會不斷新建OtherActivity 。
之所以在startActivityForResult 啟動singleTop 不起作用,在源碼中一句話決定了。
ActivityStack topStack = getFocusedStack();
ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
if (top != null && r.resultTo == null) {
Slog.d("DDY", "========------ " );
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
if (top.app != null && top.app.thread != null) {
if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
......
top.deliverNewIntentLocked(callingUid, r.intent);
上面一句話 if (top != null && r.resultTo == null) {
r.resultTo == null 表示啟動沒有返回結果。當我們的OtherActivity 用startActivity 或者startActivityForResult啟動自己,調用到底層時候都會調用到這裡。其中startActivity 啟動的時候r.resultTo == null 表示不需要返回結果,startActivityForResult啟動時候r.resultTo != null 表示要有返回結果。
startActivity 的 r.resultTo == null 成立。所以會繼續往下執行。調用
top.deliverNewIntentLocked(callingUid, r.intent)函數 ,進而使用 onNewIntent 重載OtherActivity ,而startActivityForResult 的r.resultTo != null 函數成立,會跳過這段函數。進而當做標准啟動模式,不斷新建OtherActivity,所以 singleTop 不起作用。。。。
做畢設用到的!網絡圖片的獲取這裡就以我的情況簡單的介紹一下。 首先設計布局,直接拖幾個控件就ok開始在Acitivity中增加功能在網上照一張圖片的鏈接:htt
自Android 5.0之後,谷歌公司推出了RecylerView控件,RecylerView,我想看到一個新名詞後大部分人會首先發出一個疑問,recylerview是什
這段時間的自定義View學習,學會了繪制柱狀圖、繪制折線圖、繪制進度控件,那我們今天就來聊聊另外一種自定義的View,這就是我們常見的七日年化收益折線圖效果。先看看長什麼
今天,Google Developers 中國網站 (https://developers.google.cn) 正式發布! Goog