導航:首頁 > 操作系統 > androidtaskid

androidtaskid

發布時間:2023-02-22 07:22:34

android 如何調用 底下的 activity 到前台 我不想新建

要達到這個需求,可以設置activity的啟動模式為singleTask或者singleInstance

activity一共有4中啟動模式

standard
默認模式,可以不用寫配置。在這個模式下,都會默認創建一個新的實例。因此,在這種模式下,可以有多個相同的實例,也允許多個相同Activity疊加。

例如:
若有一個Activity名為A1, 上面有一個按鈕可跳轉到A1。那麼如果點擊按鈕,便會新啟一個Activity A1疊在剛才的A1之上,再點擊,又會再新啟一個在它之上……
點back鍵會依照棧順序依次退出。

singleTop
可以有多個實例,但是不允許多個相同Activity疊加。即,如果Activity在棧頂的時候,啟動相同的Activity,不會創建新的實例,而會調用其onNewIntent方法。

例如:
若有兩個Activity名為B1,B2,兩個Activity內容功能完全相同,都有兩個按鈕可以跳到B1或者B2,唯一不同的是B1為standard,B2為singleTop。
若我意圖打開的順序為B1->B2->B2,則實際打開的順序為B1->B2(後一次意圖打開B2,實際只調用了前一個的onNewIntent方法)
若意圖打開的順序為B1->B2->B1->B2,則實際打開的順序與意圖的一致,為B1->B2->B1->B2。

singleTask
只有一個實例。在同一個應用程序中啟動的時候,若Activity不存在,則會在當前task創建一個新的實例,若存在,則會把task中在其之上的其它Activity destory掉並調用它的onNewIntent方法。
如果是在別的應用程序中啟動它,則會新建一個task,並在該task中啟動這個Activity,singleTask允許別的Activity與其在一個task中共存,也就是說,如果在這個singleTask的實例中再打開新的Activity,這個新的Activity還是會在singleTask的實例的task中。

例如:
若應用程序中有三個Activity,C1,C2,C3,三個Activity可互相啟動,其中C2為singleTask模式,那麼,無論在這個程序中如何點擊啟動,如:C1->C2->C3->C2->C3->C1-C2,C1,C3可能存在多個實例,但是C2隻會存在一個,並且這三個Activity都在同一個task裡面。
但是C1->C2->C3->C2->C3->C1-C2,這樣的操作過程實際應該是如下這樣的,因為singleTask會把task中在其之上的其它Activity destory掉。
操作:C1->C2 C1->C2->C3 C1->C2->C3->C2 C1->C2->C3->C2->C3->C1 C1->C2->C3->C2->C3->C1-C2
實際:C1->C2 C1->C2->C3 C1->C2 C1->C2->C3->C1 C1->C2

若是別的應用程序打開C2,則會新啟一個task。
如別的應用Other中有一個activity,taskId為200,從它打開C2,則C2的taskIdI不會為200,例如C2的taskId為201,那麼再從C2打開C1、C3,則C2、C3的taskId仍為201。
注意:如果此時點擊home,然後再打開Other,發現這時顯示的肯定會是Other應用中的內容,而不會是應用中的C1 C2 C3中的其中一個。

singleInstance
只有一個實例,並且這個實例獨立運行在一個task中,這個task只有這個實例,不允許有別的Activity存在。

例如:
程序有三個ActivityD1,D2,D3,三個Activity可互相啟動,其中D2為singleInstance模式。那麼程序從D1開始運行,假設D1的taskId為200,那麼從D1啟動D2時,D2會新啟動一個task,即D2與D1不在一個task中運行。假設D2的taskId為201,再從D2啟動D3時,D3的taskId為200,也就是說它被壓到了D1啟動的任務棧中。

若是在別的應用程序打開D2,假設Other的taskId為200,打開D2,D2會新建一個task運行,假設它的taskId為201,那麼如果這時再從D2啟動D1或者D3,則又會再創建一個task,因此,若操作步驟為other->D2->D1,這過程就涉及到了3個task了。

Ⅱ android 如何得到線程id

有時候,在kernel里經常收到一些系統調用,但不知道是誰調的。可以按下面的步驟找到。
1.kernel 裡面列印出線程ID、線程名、進程ID
char currtask_name[FIELD_SIZEOF(struct task_struct, comm) + 1];
printk("pid %u(%s).
",current->pid, get_task_comm(currtask_name, current));
2. 在/proc/pid/task/tid/下面有線程的信息。
另外,在user層可以通過這種方法得到線程ID.

Ⅲ android每個應用都有一個堆棧task來存放啟動的Activity實例我不能理taskid在實際開發中的作用是什麼

在開發中,Task的概念應該是與Activity棧相對應的。
換言之,Activity通過不同的啟動模式去啟動,所處的Task是不一樣的(如singletask)。
相應的也就會對畫面遷移和內存分配等問題產生影響。
暫時就想到這些~

Ⅳ Android 怎麼將json對象中的值取出來放到集合中

先解析,然後就可以調用存入了

Ⅳ taskAffinity 屬性詳解

本篇文章的目的是為了 搞清楚, 哪些情況下開啟一個 Activity 會在新的 task 運行,哪些情況下會繼續在原來的task 運行。

每個 Activity 運行時都有一個其歸屬的 task棧,我們可以用 activity.getTaskId() 的方法得到當前 activity 的taskId。 如果兩個 activity 的 taskId 不同,則他們肯定不會屬於同一個 task。

為了方便,我們在 Application 中注冊生命周期回調,類似這樣,我們列印出當前 activity 和其歸屬的 taskid。

taskAffinity 的使用方式如下,

如上圖所示,taskaffinity 可以單獨對一個 activity 使用,代表該 activity 所想歸屬的 task;
也能對application 使用,代表該 application 內聲明的所有 activity 都歸屬於這個task。

如果 activity 組件沒有聲明 taskAffinity 的話,該 activity 的 taskAffinity 屬性也是有默認值的。如果 application 指定了 taskAffinity 值,默認值就是 application 指定的 taskAffinity 值;如果 application 未指定的話,默認值就是 manifest 中聲明的包名(package 對應的字元串)。

Android 手機的任務列表就是根據不同 task 彈出的,我們可以根據任務管理器有幾個 item 圖標,來知道我們開啟了幾個 task。

是不是我指定了一個 Activity 的 taskAffinity 值(跟包名不同),運行該 Activity 時,是否就會新開這個 task棧呢?

答案是否定的, 一個 Activity 運行時所歸屬的task,默認是啟動它 的那個Activity 所在的 task (下文將會驗證)。

taskAffinity 單獨使用並不會生效。
要想其生效,需要配合其他屬性使用,或者配合 Intent.FLAG_ACTIVITY_NEW_TASK,或者配合
allowTaskReparenting 。使用時用其中的一個就行,下面將詳細介紹這兩個屬性。

Intent.FLAG_ACTIVITY_NEW_TASK 使用方式如下,

首先說下這個規則是根據測試結果反推出來的,不對之處還還請指出(捂臉。。。)

==當 AMS 發現啟動了一個帶有 FLAG_ACTIVITY_NEW_TASK 標簽的 Activity 時,會先去尋找當前是否存在這個 Activity 的 task 值(這個值具體是什麼可看 知識點2),如果不存在的話,就會創建該task,如果存在就省去了創建 task 這個步驟。然後在把要啟動的 Activity 添加到 task 中。

下面開始我們的測試,測試結果為過濾後的log日誌,並給出相應分析。

我們假定都是 Activity A 跳轉到 Activity B 中,A沒有指定 taskAffinity 屬性,B 的launchMode 為standard。

可以驗證:一個Activity 歸屬的task 是由 啟動它的 Activity 所決定的。

可以驗證,一個 Activity 的默認 task 值就是 manifest 定義的包名。

可以驗證:不指定 FLAG_ACTIVITY_NEW_TASK的話, 即使 taskAffinity 不同,一個Activity 歸屬的task 仍然是由 啟動它的 Activity 所決定的。

可以驗證:即使 使用了 FLAG_ACTIVITY_NEW_TASK,但由於兩者的 taskAffinity 相同,所以仍然不會開啟一個新的task。

可以驗證:開啟一個新task 的條件是 FLAG_ACTIVITY_NEW_TASK 和 taskAffinity 不同 缺一不可。

可以得出:未指定 FLAG_ACTIVITY_NEW_TASK 和 新的 taskAffinity 時,這兩種啟動模式對task 沒有影響

可以得出:
singleinstance 啟動模式本身就是會開啟一個新的task 裝載 這個Activity,且task 中只有這一個 Activity。
經判斷得知,AMS 是先對 launchMode 做判斷 再處理 FLAG_ACTIVITY_NEW_TASK 的,如果是 singleinstance ,則會直接開啟一個task。

上面七個 case 均是在同一個app 內的,現在考慮跨進程調用的情況,A在 app1,B在app2, 此時 B 的默認 task 肯定是和 A 不同的
我們可以通過隱式啟動的方式啟動B,B 仍然是標准啟動模式。
類似這樣

++下文 所有的 App1的log標識為 MyApplication,App2 的標識為 MyApplication2。++

可以得出:case 8 與 case 3 的本質是相同的,僅僅是 A 和 B 的taskA 屬性不同,所以沒有開啟新的task。
我們還可以看出,task 是可以跨進程的,即一個 task 中的 Activities 是可以運行在不同的進程中的。(關於 A 和 B 不在同一個進程讀者可自行驗證)

可以得出:case 9 與 case 5 的本質是相同的。

至此,Intent 的 FLAG_ACTIVITY_NEW_TASK 屬性 應該算是講解清楚了。

我們還可以得出一個有意思結論,那就是 AMS 分配的taskid 是線性遞增的,每次開啟一個新的task ,taskid 永遠都是 +1 的操作。

測試該屬性的話,應該先把 FLAG_ACTIVITY_NEW_TASK 屬性去掉。

allowTaskReparenting 這個屬性指的是一個 Activity 運行時,可以重新選擇自己所屬的task。基本是在跨app 間調用時,我們在上面的case 8 的基礎上,對 Activity 做如下修改

當 A 啟動 B 時,這時雖然是在兩個進程中的,但其歸屬的task 是同一個,這時我們回到後台,在桌面點擊 B 的應用圖標,我們會發現 log 日誌如下:
其中 MyApplication 代表 app1,MyApplication2代表 app2。

log 日誌如下:

此 case 正好驗證之前的解析規則,若 Activity taskAffinity指定的task 已經存在,是會復用之前的task,而不會再重新創建一個新的task。

Ⅵ Android基礎知識

一、activity

1.一個activity就是一個類,繼承activity;

2.需要復寫onCreate()方法;

3.每一個activity都需要在AndroidMainfest.xml清單上進行配置;

4.為activity添加必要的控制項。

二、布局

線性布局:LinearLayout

1.填滿父空間:fill_parent、match_parent

2.文本多大空間就有多大:warp_content

3.文字對齊方式:gravity

4.占屏幕的比例:layout_weight="1"  水平方向,則width=0,垂直方向,則height=0

5.一行顯示,空間不夠會省略:singleLine="ture"  false會換行

6.背景:background="#ffffff"

7.水平布局:orientation="horizontal"

垂直布局:orientation="vertivcal"

表格布局:TableLayout

1.內邊距:padding

2.外邊距:marginLeft\Start、Right\End、Top、Bottom

三、RelativeLayout相對布局

layout_above 將該控制項的底部置於給定ID控制項之上

layout_below 將該控制項的頂部置於給定ID控制項之下

layout_toLeftOf 將該控制項的右邊緣和給定ID控制項的左邊緣對齊

layout_toRightOf 將該控制項的左邊緣和給定ID控制項的右邊緣對齊

layout_alignBaseline 該控制項的baseline和給定ID的控制項的Baseline對齊

layout_alignBottom 該控制項的底部邊緣和給定ID的控制項的底部邊緣對齊

layout_alignLeft 該控制項的左邊緣和給定ID的控制項的左邊緣對齊

layout_alignRight 該控制項的右邊緣和給定ID的控制項的右邊緣對齊

layout_alignTop 該控制項的頂部邊緣和給定ID的控制項的頂部邊緣對齊

layout_alignparentBottom 如果該值為true,則該控制項的底部和父控制項的底部對齊layout_alignParentLeft 如果該值為true,則該控制項的左邊和父控制項的左邊對齊

layout_alignParentRight 如果該值為true,則該控制項的右邊和父控制項的右邊對齊

layout_alignParentTop 如果該值為true,則該控制項的上邊和父控制項的上邊對齊

layout_centerHorizontal 如果該值為true,則該控制項將被置於水平方向的中央

layout_centerInParent 如果該值為true,則該控制項將被置於父控制項水平和垂直方向的中央

layout_centerVertival 如果該值為true,則該控制項將被置於垂直方向的中央

四、一個Intent對象包含一組信息

1.Component name

2.Action

3.Data

4.Category

5.Extras

6.Flags

Intent intent = new Intent(this, SecondActivity.class);

startActivity(intent);  //startActivity方法

intent.putExtra("Key", "Value");  //鍵值對

intent = getIntent();

String value = intent.getStringExtra("Key");    //通過鍵提取數據

五、初級控制項:EditText、TextView、Button

1.獲取EditText的值

String value = EditText.getText().toString();

2.將值放到Intent對象中

Intent intent = new Intent();

intent.putExtra("one",value )

intent.setCalss(Activity.this, OtherActivity.class);

3.使用這個Intent對象來啟動Otheractivity

Activity.this.startActivity(intent);

4.將監聽器的對象綁定到按鈕對象上

button.setOnclickListener(new Listener());

5.得到Intent對象當中的值

Intent intent = getIntent();

String value1 = intent.getStringExtra("one");

int value2 = Integer.parseInt(value);

六、其他初級控制項使用

①ImageView

②RadioGroup和RadioButton

setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener())

③Checkbox

setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener())

④Menu

1.當客戶點擊MENU按鈕的時候,調用onCreateOptionMenu()方法

public boolean onCreateOptionMenu(Menu menu){

menu.add(0,1,1,R.string.id);

}

2.當客戶點擊MENU內部的具體某一個選項時,調用onOptionItemSelected()方法

public boolean onOptionItemSelected(MenuItem item){

if(item.getItemId() == 1){

finish();

}

return super.onOptionItemSelected(item);

}

七、Activity的生命周期

1.第一次創建時調用

protected void onCreat(Bundle saveInstanceState);

2.顯示出來時調用

protected void onStrat();

3.獲得用戶焦點時調用(可操作)

protected void onResume();

4.點擊彈出第二個Activity時調用

protected void onPause();

5.當第一個Activity不可見時調用

protected void onStop();

6.當返回第一個Activity時調用,代替OnCreate,因為沒被銷毀

protected void onRestart();

7.當返回第一個Activity時調用(先執行onStop,在執行,因為第二個Activity被銷毀,不能返回獲取,只能通過onCreat,onStart,onResume再創建)

protected void onDestory();

八、Task

1.Task是存放Activity的Stack棧。當點擊啟動第二個Activiry時,第一個Activtiy會被壓入Stack棧當中,第二個Activity會位於棧的頂部;當返回第一個Activtiy時,第二個Activity會被彈出Stack,第一個Activity會位於棧的頂部,以此類推。

注釋:當調用finish()時,當前的Activity會被Destory掉,棧中的Activity會消失。

2.當Activity都從Stack退出後,則就不存在Task。

九、高級控制項

①進度條ProgressBar

水平進度條style="?android:attr/progressBarStyleHorizontal"

圓圈進度條style="?android:attr/progressBarStyle"

用戶可視的visibility="gone"

②列表ListView

十、其他控制項

A.下拉菜單Spinner

1.創建一個ArrayAdapter:

ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(

this, //指上下文對象

R.array.plant_array, //引用了在文件中定義的String數組

android.R.layout.simple_spinner_item);//用來指定Spinner的樣式,可替換自定義

adapter.setDropDownViewResource(

android.R.layout.simple_spinner_dropdown_item);//設置Spinner當中每個條目的樣式

2.得到Spinner對象,並設置數據:

spinner=(spinner)findViewById(R.id.spinnerId);

spinner.setAdapter(adapter);

spinner.setPrompt("測試");//標題

3.創建監聽器

class SpinnerOnSelectListener implements OnItemSelectedListener{

@override

public void onItemSelected(

AdapterView<?> adapterView,//整個列表對象

View view,//被選中的具體條目對象

int position,//位置

long id){ //id

String selected = adapterView.getItemAtPosition(position).toString();

}

@override

public void onNothingSelected(AdapterView<?> adapterView){

S.o.p("nothingSelected");

}

}

4.綁定監聽器

spinner.setOnItemSelectedListener(new SpinnerOnSelectListener());

註:第二種動態設計

1.創建ArrayList對象

List<String> list = new ArrayList<String>();

list.add("test1");

2. 調用方法

ArrayAdapter adapter = new ArrayAdapter(

this, //指上下文對象

R.layout.item, //引用了指定了下拉菜單的自定義布局文件

R.id.textViewId,//id

list);//數據

3.得到Spinner對象,並設置對象

spinner.setAdapter(adapter);

spinner.setPrompt("測試");//標題

3.創建監聽器

class SpinnerOnSelectListener implements OnItemSelectedListener{

@override

public void onItemSelected(

AdapterView<?> adapterView,//整個列表對象

View view,//被選中的具體條目對象

int position,//位置

long id){ //id

String selected = adapterView.getItemAtPosition(position).toString();

}

@override

public void onNothingSelected(AdapterView<?> adapterView){

S.o.p("nothingSelected");

}

}

4.綁定監聽器

spinner.setOnItemSelectedListener(new SpinnerOnSelectListener());

B.DatePicker和DatePickerDialog

1.聲明一個監聽器,使用匿名內部類

DatePickerDialog.OnDateSetListener onDateSetListener

= new DatePivkerDialog.OnDateSetListener(){

public void onDateSet(

DatePicker view,

int year,

int monthOfYear,

int dayOfMonth){

S.o.p(year+"-"+motnOfYear+"-"+dayOfMonth)

}

}

2.復寫onCreateDialog(int id)方法:

@override

protected Dialog onCreateDialog(int id){

switch(id){

case DATE_PICKER_ID:

return new DatePickerDialog(this,onDateSetListener,2019,11,25);

}

return null;

}

3.使用時調用showDialog()方法

showDialog(DATE_PICKER_ID);

C.AutoCompleteTextView

B.Widget

C.Animatin

十一、實現ContentProvider過程

1.定義一個CONTENT_URI常量

2.定義一個類,繼承ContentProvider

3.實現query、insert、update、delete、getType和onCreate方法

4.在AndroidManifest.xml當中進行聲明

Ⅶ android啟動模式設置為single task任務棧為什麼

在Android中每個界面都是一個Activity,切換界面操作其實是多個不同Activity之間的實例化操作。在Android中Activity的啟動模式決定了Activity的啟動運行方式。 Android總Activity的啟動模式分為四種: Activity啟動模式設置: <activity android:name=".MainActivity" android:launchMode="standard" /> Activity的四種啟動模式: 1. standard 模式啟動模式,每次激活Activity時都會創建Activity,並放入任務棧中。 2. singleTop 如果在任務的棧頂正好存在該Activity的實例, 就重用該實例,否者就會創建新的實例並放入棧頂(即使棧中已經存在該Activity實例,只要不在棧頂,都會創建實例)。 3. singleTask 如果在棧中已經有該Activity的實例,就重用該實例(會調用實例的onNewIntent())。重用時,會讓該實例回到棧頂,因此在它上面的實例將會被移除棧。如果棧中不存在該實例,將會創建新的實例放入棧中。 4. singleInstance 在一個新棧中創建該Activity實例,並讓多個應用共享改棧中的該Activity實例。一旦改模式的Activity的實例存在於某個棧中,任何應用再激活改Activity時都會重用該棧中的實例,其效果相當於多個應用程序共享一個應用,不管誰激活該Activity都會進入同一個應用中。 其中standard是系統默認的啟動模式。 下面通過實例來演示standard的運行機制: 1 private TextView text_show; 2 private Button btn_mode; 3 4 @Override 5 public void onCreate(Bundle savedInstanceState) { 6 super.onCreate(savedInstanceState); 7 setContentView(R.layout.activity_main); 8 9 text_show = (TextView) this.findViewById(R.id.text_show); 10 11 text_show.setText(this.toString()); 12 13 btn_mode = (Button) this.findViewById(R.id.btn_mode); 14 15 } 16 //按鈕單擊事件 17 public void LaunchStandard(View v){ 18 startActivity(new Intent(this,MainActivity.class)); 19 20 text_show.setText(this.toString()); 21 }

Ⅷ 在一個Activity的java程序中,具體看問題描述

1、Intent

Intent是各個組件之間交互的一種重要方式,它不僅可以指明當前組件想要執行的動作,而且還能在各組件之間傳遞數據。Intent一般可用於啟動Activity、啟動Service、發送廣播等場景。

Intent大致可分為2中:

1、顯示Intent

2、隱式Intent

1.1、顯示Intent打開Activity

fun openActivity(){
val intent = Intent(this, KotlinFirstActivity::class.java)

intent.putExtra("param", "testParams")

startActivity(intent)

}

注意:KotlinFirstActivity::class.java就相當於Java中的KotlinFirstActivity.class。

1.2、隱式Intent打開程序內的Activity

相比於顯示Intent,隱式Intent並不指明啟動那個Activity而是指定了一系列的action和category,然後交由系統去分析找到合適的Activity並打開。

什麼是合適的Activity,其實就是和隱式Intent中指定的action和category完全匹配的Activity,而action和category我們可以在AdnroidManifest中指定。

在標簽中配置了action和category,只有和隱式Intent中的action和category完全匹配才能正常的打開該頁面。

val intent = Intent("com.example.abu.alertdialogdemo.ACTION_START")

startActivity(intent)

不是說action和category要完全匹配才能打開頁面嗎?這是因為android.intent.category.DEFAULT是一種默認的category,在調用startActivity()時會自動將這個category添加到Intent中。所以在Manifest中一定不要忘記配置這個默認的category:android.intent.category.DEFAULT,否則會報錯。

還有一點需要注意:Intent中只能添加一個action,但是可以添加多個category。

1.3、隱式Intent打開程序外的Activity

比如我們要打開系統的瀏覽器

fun openWeb(view: View) {
val intent = Intent(Intent.ACTION_VIEW)

intent.data = Uri.parse("https://www..com")

startActivity(intent)

}

Intent.ACTION_VIEW是系統內置的動作,然後將https://www..com通過Uri.parse()轉換成Uri對象,傳遞給intent.setData(Uri uri)函數。Kotlin中intent.data=Uri.parse("https://www..com")就相當於Java中的intent.setData(Uri.parse("https://www..com")),這是Kotlin中的語法糖。

與此對應在標簽中配置一個標簽,用於更精確的指定當前Activity能夠相應的數據。標簽中主要可以配置一下內容:

1、android:scheme:用於指定數據的協議部分,如https

2、android:host:用於指定數據的主機名部分,如www..com

3、android:port:用於指定數據的埠,一般緊隨主機名後

4、android:path:用於指定數據的路徑

5、android:mimeType:用於指定支持的數據類型

只有當標簽中指定的內容和Intent中攜帶的data完全一致時,當前Activity才能響應該Intent。下面我們通過設置data,讓它也能響應打開網頁的Intent。

我們在ThirdActivity的中配置當前Activity能夠響應的action是Intent.ACTION_VIEW的常量值,而category指定了默認的category值,另外在標簽data中我們通過android:scheme="https"指定了數據的協議必須是https。另外由於AndroidStudio認為能夠響應ACTION_VIEW的Activity都應該加上BROWSABLE的category,否則會報出警告。加上BROWSABLE的category是為了實現deep link 功能和目前學習無關,所以我們在intent-filter標簽上添加tools:ignore="AppLinkUrlError"忽略警告。

然後我們就能通過隱式Intent的方法打開ThirdActivity了,代碼如下:

val intent= Intent(Intent.ACTION_VIEW)

intent.data=Uri.parse("https:")

startActivity(intent)

除了指定android:scheme為https我們也能隨意指定它的值,只需要保證AndroidManifest中設置的值和Intent中設置的data相對應即可。

2、Activity的生命周期

Activity類中定義了7個回調方法,覆蓋了Activity聲明周期的每一個環節。

1、onCreate(): 在Activity第一次創建時調用

2、onStart():在Activity可見但是沒有焦點時調用

3、onResume():在Activity可見並且有焦點時調用

4、onPause():這個方法會在准備啟動或者恢復另一個Activity時調用,我們通常在該方法中釋放消耗CPU的資源或者保存數據,但在該方法內不能做耗時操作,否則影響另一個另一個Activity的啟動或恢復。

5、onStop():在Activity不可見時調用,它和onPause主要區別就是:onPause在失去焦點時會調用但是依然可見,而onStop是完全不可見。

6、onDestory():在Activity被銷毀前調用

7、onRestart():在Activity由不在棧頂到再次回到棧頂並且可見時調用。

為了更好的理解Activity的生命周期,看下圖

Activity生命周期.png

3、體驗Activity的生命周期

下面我們通過實例更直觀的看下Activity的生命周期過程。

1、打開FirstActivity,生命周期過程如下

FirstActivity onCreate

FirstActivity onStart

FirstActivity onResume

2、在FirstActivity中打開SecondActivity,生命周期過程如下

FirstActivity onPause

SecondActivity onCreate

SecondActivity onStart

SecondActivity onResume

FirstActivity onStop

可以看到在打開SecondActivity時FirstActivity的onPause會執行,所以在onPause中是不能做耗時操作的,否則會影響SecondActivity的打開。

3、按返回鍵回到FirstActivity,生命周期過程如下

SecondActivity onPause

FirstActivity onRestart

FirstActivity onStart

FirstActivity onResume

SecondActivity onStop

SecondActivity onDestroy

可以看到在返回FirstActivity時會調用SecondActivity的onPause,如果SecondActivity的onPause中做了耗時操作的話,那麼也會影響Activity的返回。而且當FirstActivity再次回到棧頂時會調用其onRestart,此時並不會執行onCreate因為FirstActivity並沒有銷毀。

4、Activity被回收了時的生命周期

現在描述一種場景:打開ActivityA,然後在ActivityA的頁面中打開ActivityB,此時ActivityA不在棧頂了如果內存不足可能會被回收,此時從ActivityB再回到ActivityA,下面描述下整個過程的生命周期。

1、打開ActivityA,執行的生命周期

ActivityA onCreate

ActivityA onStart

ActivityA onResume

2、打開ActivityB執行的生命周期

ActivityA onPause

ActivityB onCreate

ActivityB onStart

ActivityB onResume

ActivityA onStop

3、此時因內存不足,導致ActivityA被回收了,並返回ActivityA

ActivityA onDestory

ActivityB onPause

ActivityA onCreate

ActivityA onStart

ActivityA onResume

ActivityB onStop

從上面可以看出在ActivityA被回收後再次回到ActivityA時不再調用ActivityA的onRestart了,而是調用了ActivityA的onCreate,因為ActivityA已經被銷毀了。

5、Activity被銷毀,其中的臨時數據怎麼辦

ActivityA被銷毀了,這也就說明其中的臨時數據也會丟失了,比如ActivityA中有一個EditText,我們在其中輸入了一段文字,然後啟動ActivityB,此時由於內存緊張處於停止狀態的ActivityA被回收了,返回到ActivityA你會發現EditText中輸入的文字不見了,因為ActivityA重新創建了。

為此Activity提供了onSaveInstanceState方法,該方法能確保在被回收之前被調用,我們就能在onSaveInstanceState方法中進行臨時數據的保存,然後我們可以在onCreate(savedInstanceState: Bundle?)中利用savedInstanceState進行數據的恢復。Activity被回收重新創建時onCreate(savedInstanceState: Bundle?)中的savedInstanceState不再為null否則為null,其中帶有在savedInstanceState中保存的所有數據。

具體代碼如下:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

Log.e("tag", "$tag onCreate")

//恢復數據

val tempData = savedInstanceState?.getString("data") ?: ""

et.setText(tempData)

}

//保存數據

override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)

Log.e("tag", "$tag onSaveInstanceState")

val tempData = et.text.toString().trim()

outState?.putString("data", tempData)

}

6、onSaveInstanceState()調用時機

1、用戶按下HOME鍵

2、長按HOME鍵進入其他程序

3、按下電源鍵關閉屏幕

4、從ActivityA跳轉到一個新的Activity

5、屏幕方向切換時,如從豎屏變成橫屏

總而言之,onSaveInstanceState()是在你的Activity有可能在未經允許的情況下被回收時調用,Activity被銷毀之前onSaveInstanceState()肯定會被觸發,我們可以onSaveInstanceState()中保存臨時數據,持久化的數據可以在onPause()中保存。

另外,雖然屏幕方向切換時,會造成Activity的重建會調用onSaveInstanceState(),但是不建議使用onSaveInstanceState()進行數據的保存,我們可以禁止屏幕的旋轉或禁止屏幕旋轉時Activity的重建。

禁止屏幕旋轉

可以在Mainifest中設置屏幕固定為豎屏

android:screenOrieritation="portrait"

禁止屏幕旋轉時Activity的重建

android:configChanges="orientation丨keyboardHidden丨screenSize"

7、Activity的啟動模式

啟動模式分為4種:

1、standard

2、singleTop

3、singleTask

4、singleInstance

我們可以在Manifest中通過android:launchMode指定啟動模式。

7.1、standard模式

如果不顯示指定啟動模式,那麼Activity的啟動模式就是standard,在該模式下不管Activity棧中有無該Activity,均會創建一個新的Activity並入棧,並處於棧頂的位置。

7.2、singleTop模式

1、要啟動的Activity位於棧頂

在啟動一個ActivityA時,如果棧頂的Activity就是ActivityA,那麼就不會重新創建ActivityA,而是直接使用,此時並不會調用ActivityA的onCreate(),因為並沒有重新創建Activity,ActivityA的生命周期如下:

ActivityA onPause

ActivityA onNewIntent

ActivityA onResume

可以看到調用了onNewIntent(intent: Intent?),我們可以在onNewIntent(intent: Intent?)中通過intent來獲取新傳遞過來的數據,因為此時數據可能已經發生了變化。

2、要啟動的Activity不在棧頂

雖然我們指定了ActivityA的啟動模式為singleTop,但是如果ActivityA在棧中但是不在棧頂的話,那麼此時啟動ActivityA的話會重新創建一個新的ActivityA並入棧,此時棧中就有2個ActivityA的實例了。

7.3、singleTask模式

如果准備啟動的ActivityA的啟動模式為singleTask的話,那麼會先從棧中查找是否存在ActivityA的實例:

場景一、如果存在則將ActivityA之上的Activity都出棧,並調用ActivityA的onNewIntent()。

場景二、如果ActivityA位於棧頂,則直接使用並調用onNewInent(),此時和singleTop一樣。

場景三、 如果棧中不存在ActivityA的實例則會創建一個新的Activity並入棧。

場景一:ActivityA啟動ActivityB,然後啟動ActivityA,此時生命周期過程:

ActivityB onPause

ActivityA onRestart

ActivityA onStart

ActivityA onNewIntent

ActivityA onResume

ActivityB onStop

ActivityB onDestroy

此時ActivityA不在棧頂,ActivityA之上有ActivityB,所以在啟動ActivityA時ActivityA之上的ActivityB會出棧,ActivityA將置於棧頂,所以ActivityA的onRestart和ActivityB的onDestory會執行。

場景二:ActivityA啟動ActivityA,此時生命周期過程:

ActivityA onPause

ActivityA onNewIntent

ActivityA onResume

此時ActivityA位於棧頂,此時singleTask和singleTop作用一樣,都是直接使用ActivityA,並且會調用ActivityA的onPause、onNewIntent、onResume。

場景三:ActivityA啟動ActivityB,此時生命周期過程:

ActivityA onCreate

ActivityA onStart

ActivityA onResume

7.4、singleInstance模式

不同於另外3個模式,指定singleInstance模式的Activity會啟動一個新的返回棧來管理這個Activity(其實如果singleTask模式指定了不同的taskAffinity,也會啟動一個新的返回棧),這么做的意義是什麼?

想像一個場景:如果我們程序內的一個Activity是允許其他程序訪問的,如果想實現其他程序和我們程序能共享這個Activity實例,該怎麼實現呢?使用前面3中模式是無法做到的,因為每個應用程序都有自己的返回棧,同一個Activity在不同返回棧中肯定都創建了新的實例,而使用singleInstance就可以解決這個問題。在這種模式下,會有一個單獨的返回棧來管理這個Activity,無論哪個應用程序來訪問這個Activity,都在同一個返回棧中,也就解決了共享Activity實例的問題。

為了更好的理解下面我們實戰一下:

1、將ActivityB的啟動模式修改為singleInstance

android:name=".ActivityB"

android:launchMode="singleInstance" />

2、在ActivityA、ActivityB、ActivityC的onCreate中列印taskId

##ActivityA

val tag = javaClass.simpleName

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

Log.e("TAG", "$tag taskId=$taskId")

}

##ActivityB

val tag = javaClass.simpleName

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContentView(activity_second)

Log.e("TAG", "$tag taskId=$taskId")

}

##ActivityC

val tag = javaClass.simpleName

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContentView(activity_c)

Log.e("TAG", "$tag taskId=$taskId")

}

在Kotlin中javaClass是當前實例的Class對象,相當於Java的getClass().

在Kotlin中ActivityB::class.java是獲取ActivityB類的Class對象,相當於Java中的ActivityB.class。

3、啟動ActivityA->啟動ActivityB->啟動ActivityC,taskId列印結果如下:

ActivityA taskId=4163

ActivityB taskId=4164

ActivityC taskId=4163

可以看到ActivityB的taskId是不同於ActivityA 和ActivityC的,這也說明了ActivityB 是在一個單獨的棧中的,並且返回棧中只有這一個Activity。

4、在ActivityC中按返回鍵,返回到ActivityA,再按返回鍵返回到ActivityB,這是為什麼呢?其實很好理解:ActivityA 和ActivityC 在同一個返回棧中,在ActivityC 中按返回鍵ActivityC 出棧,此時ActivityA就位於棧頂了,ActivityA就展示在界面上了,在ActivityA中再按返回鍵,這是當前的返回棧已經空了,於是就展示了另一個返回棧棧頂的ActivityB了。
————————————————
版權聲明:本文為CSDN博主「保瓶兒」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_31211457/article/details/114052641

Ⅸ Android 深入探討sigleTask和singletop的區別

1.singleTask和singletop都是保真了Activity在棧中的唯一性

2.singleTask和singleTop實例存在時,都不會重新創建 new task

不同之處有如下幾點:

如果singleTask啟動的ActivityA位於棧底,在棧頂startActivity到這個ActivityA時會調動
onNewIntent->onStart->onResume。

但singleTask啟動的的ActivityA不存在時,會重新創建ActivityA,調用方式OnCreate->OnStart->OnResume

2.如果singletop啟動的ActivityB在棧底時,在棧頂startActivity到這個ActivityB時會重新調動
onCreate->onStart->onResume,但不會調用OnDestroy

並且singletop啟動的的ActivityB不存在時,會重新創建ActivityB,調用方式OnCreate->OnStart->OnResume

3.singleTask在棧底時,從棧頂startActivity到棧底ActivityA,那麼該棧startActivity的發起者的中間部分Activity會被銷毀。而singletop是逐級跳躍到棧頂

singleTask

追加一點singleInstance,雖然也是保證唯一性,但改模式的Activity是全局性的唯一性,生命周期和應用程序相同,不能及時回收,此外的話Activity在MVC充當Controller的角色,

這點顯然對singleIntance來說不適合,因此不建議使用。

4.singleTask不適合充當ChildActivity,但singletop適合

5.對作業棧,默認情況下,沒有任何影響,因為棧的taskid是相同的,可以獲取getTaskid(),默認情況下每個activity的taskid相同

但是,如果自定義了棧的標簽(這個標簽相同的singletask activity在同一個作業棧中),那麼taskid就會初選差別

android:taskAffinity="com.sample.lanchmode.tester.main",那麼一旦另一個作業棧被銷毀,下次必然重建(相信我,這不是廢話)。

為了一句不是廢話,我需要來證明一下。

當我們的初始載入WelcomeActivity界面--->HomeActivity界面時,如果將HomeActivity的啟動模式設置為sigleTask+android:taskAffinity="自定義(一般是類名)",

①那麼WelcomeActivity銷毀後,在到達HomeActivity之後,HomeActivity回作為一個新的作業棧棧底而存在,所以由HomeActivity啟動的Activity的TaskId和HomeActivity相同。

②這個過程,WelcomeActivity和HomeActivity的TaskId是不相同的,問題出現了,當我們按下 Home鍵,然後在點擊桌面上的app圖標你會發現,WelcomeActivity再次出現了,

而且再次進入了HomeActivity,並且這個HomeActivity調用了OnNewIntent,卻沒掉用OnCreate,所以來說他一直存在這,但你需要再次過渡才能找到它。

(對於追求捕獲Home鍵讓app退出的讀者是一個喜訊,這樣可以做到每次Home之後都能再次進入登錄界面),在這個過程中沒有直接進入HomeActivity,而是WelcomeActivity(有人說不對么,不應該是這樣么,在這里不想解釋)。

注意,使用了不同作業棧的Activity,會在最近打開的app顯示一個應用會出現2個界面。

在這里,需要強調一下singleTask+android:taskAffinity不一定必須使用,請依據需求而定,網上有人推薦使用,但我卻想說,不要盲目,並不是所有的應用都適合。

1-->
singleTask+android:taskAffinity對於效率而言,優勢並不存在,比如設置進程的,但對於帶有登錄狀態的app需要慎用,否則造成信息泄露等問題,開發中只使用singleTask即可。

2-->
singleTask+android:taskAffinity適用於單用戶保密性的app(可做到Home之後下次必須登錄才能查看信息),建議在這方面試試。

轉載

Ⅹ android 從第一個頁面跳轉到第二個頁面之後 在第二個頁面的按鈕上開始一個倒計時 要怎麼實現

可以使用Handler來做


比如下面的代碼片段,開始一個30秒的倒計時

在Application.onCreate()里TestMain.getInstance().setContext(this);

或則在你的第二個頁面onCreate()里TestMain.getInstance().setContext(this);


之後啟動倒計時並刷新頁面

TestMain.getInstance().startCountdownTask(new CountdownTask("taskid1", 30));

publicclassTestMain{

//用於保存倒計時任務已經完成的計數
;
;

=newTestMain();
privateTestMain(){}

(){
returnINSTANCE;
}

//在主線程里調用,比如Application.onCreate()中TestMain.getInstance().setContext(this);
publicvoidsetContext(Contextcontext){
mCountdownPrefs=context.getSharedPreferences("countdwon",Context.MODE_PRIVATE);
mCountdownHandler=newHandler();

}


//在需要倒計時任務的時候調用
publicvoidstartCountdownTask(){
//如果有未完成的倒計時任務,讀取上次倒計時到幾了,否則就是設置的count次
intcount=mCountdownPrefs.getInt(countdownTask.taskId,countdownTask.count);
countdownTask.count=count;
//首先執行一次
countdownTask.notify(countdownTask.count);
//之後每一秒執行一次
mCountdownHandler.postDelayed(newRunnable(){
@Override
publicvoidrun(){
//1秒執行一次
if(countdownTask.countDown()){
mCountdownHandler.postDelayed(this,1000);
}else{
//倒計時結束
mCountdownHandler.removeCallbacks(this);
//移除任務
mCountdownPrefs.edit().remove((countdownTask.taskId)).commit();
}
}
},1000);

}

{
/**倒計時起始值*/
privateintcount=30;
/**倒計時任務id*/
privateStringtaskId="";

publicCountdownTask(intcount,StringtaskId){
this.count=count;
this.taskId=taskId;
}

privatebooleancountDown(){
count--;
booleanisContinue=count>=0;
notify(Math.max(count,0));
returnisContinue;
}

//通知更新
publicvoidnotify(intcurrent){
//UI更新倒計時數字,current是當前倒計時到多少了
}
}
}
閱讀全文

與androidtaskid相關的資料

熱點內容
vc6查看編譯的錯誤 瀏覽:595
心理大全pdf 瀏覽:1002
區域鏈加密幣怎麼樣 瀏覽:341
查找命令符 瀏覽:95
壓縮工具zar 瀏覽:735
白盤怎麼解壓 瀏覽:474
辰語程序員學習筆記 瀏覽:47
程序員被公司勸退 瀏覽:523
java三子棋 瀏覽:692
加密空間怎麼強制進入 瀏覽:345
ug分割曲線命令 瀏覽:209
學碼思程序員 瀏覽:609
自考雲學習app為什麼登不上 瀏覽:410
domcer伺服器晝夜更替怎麼搞 瀏覽:436
plc和單片機哪個好 瀏覽:535
帝國神話組建雲伺服器 瀏覽:827
鄧散木pdf 瀏覽:199
方舟怎麼直連伺服器圖片教程 瀏覽:563
假相pdf 瀏覽:336
找對象找程序員怎麼找 瀏覽:976