編輯:關於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 不起作用。。。。
Android開發之網絡圖片獲取
做畢設用到的!網絡圖片的獲取這裡就以我的情況簡單的介紹一下。 首先設計布局,直接拖幾個控件就ok開始在Acitivity中增加功能在網上照一張圖片的鏈接:htt
談談Android開發之RecyclerView的使用全解
自Android 5.0之後,谷歌公司推出了RecylerView控件,RecylerView,我想看到一個新名詞後大部分人會首先發出一個疑問,recylerview是什
Android自定義View——實現理財類APP七日年化收益折線圖效果
這段時間的自定義View學習,學會了繪制柱狀圖、繪制折線圖、繪制進度控件,那我們今天就來聊聊另外一種自定義的View,這就是我們常見的七日年化收益折線圖效果。先看看長什麼
【我的Android進階之旅】 Google Developers中國網站發布啦!
今天,Google Developers 中國網站 (https://developers.google.cn) 正式發布! Goog