Activity
Activity簡(jiǎn)介
四大組件之一,在應(yīng)用中一個(gè)Actvity可以用來表示一個(gè)界面,意思為“活動(dòng)”,代表Activity組件啟動(dòng),活動(dòng)結(jié)束,代表一個(gè)Activity的生命周期結(jié)束。一個(gè)android應(yīng)用必須通過Activity來運(yùn)行和開始。Activity的生命周期交給系統(tǒng)同一管理。
- Application
- Activity
- Activity棧
- Task:一個(gè)Activity棧對(duì)應(yīng)一個(gè)任務(wù)
Activity的狀態(tài)
在Android中,Activity擁有三個(gè)基本的狀態(tài):
1.Resumed :一個(gè)新的Activity啟動(dòng)入棧后,它在屏幕最前端,處于棧的最頂端,此時(shí)他處于可見并且可以和用戶交互的激活狀態(tài)
2.Paused :當(dāng)Avtivity被另一個(gè)透明或者Dailog樣式的Activity覆蓋時(shí)的狀態(tài)。此時(shí)它依然與窗口管理器保持連續(xù),系統(tǒng)繼續(xù)維護(hù)其內(nèi)部的狀態(tài),所以它任然可見,但是它失去了焦點(diǎn),故不可和用戶交互。
3.Stop :當(dāng)Activity被另一個(gè)Activity覆蓋、失去焦點(diǎn)并不可見時(shí)處于Stop狀態(tài)。
Activity有七個(gè)基本的方法:
/**
* Activity的三個(gè)狀態(tài)和七個(gè)生命狀態(tài)分析
*/
public class MainActivity extends Activity {
/**
* 當(dāng)前Activity被銷毀時(shí)調(diào)用,通常在該方法中釋放資源,當(dāng)前Activity被kill
*/
@Override
protected void onDestroy() {
super.onDestroy();
System.out.println("MainActivity--onDestory");
}
/**
* 當(dāng)其他Activity(透明或窗口模式時(shí))進(jìn)入時(shí),該方法會(huì)被調(diào)用,讓當(dāng)前Activity進(jìn)入Paused狀態(tài)(暫停狀態(tài))
* 當(dāng)前Activity任然可見但是不可與用戶交互
* 如果其他更高優(yōu)先級(jí)的APP需要內(nèi)存時(shí),當(dāng)前Activity,當(dāng)前ACtivity可能會(huì)被kill
* 當(dāng)前Activity被返回時(shí),會(huì)調(diào)用onResume
* */
@Override
protected void onPause() {
super.onPause();
System.out.println("MainActivity--onPause");
}
/**
* 在onstart方法后調(diào)用,該方法執(zhí)行完成后,用戶科技進(jìn)行交互,當(dāng)前Activity進(jìn)入Resumed狀態(tài)
* 當(dāng)一個(gè)paused狀態(tài)的Activity被重新返時(shí),會(huì)再次調(diào)用該方法,讓Activity進(jìn)入運(yùn)行狀態(tài)
*
*/
@Override
protected void onResume() {
super.onResume();
System.out.println("MainActivity--onResume");
}
/**
* 當(dāng)一個(gè)Stopped狀態(tài)的Activity被返回后調(diào)用,之后調(diào)用onStart方法,進(jìn)入運(yùn)行狀態(tài)
*/
@Override
protected void onRestart() {
super.onRestart();
System.out.println("MainActivity--onRestart");
}
/**
* 在onCreate方法之后調(diào)用,用于顯示界面但能和用戶交互
*/
@Override
protected void onStart() {
super.onStart();
System.out.println("MainActivity--onStart");
}
/**
* 當(dāng)其他Activity完全覆蓋該Activity時(shí),會(huì)被調(diào)用,當(dāng)前Activity進(jìn)入Stopped進(jìn)入停止?fàn)顟B(tài)不可見
* 如果其他更高優(yōu)先級(jí)的APP需要內(nèi)存時(shí),當(dāng)前Activity,當(dāng)前ACtivity可能會(huì)被kill
* 當(dāng)前Activity被返回時(shí),會(huì)調(diào)用onRestart方法
*/
@Override
protected void onStop() {
super.onStop();
System.out.println("MainActivity--onStop");
}
/**
* Activity創(chuàng)建時(shí)第一個(gè)被調(diào)用的方法,
* 通常在該方法中加載布局文件,初始化UI組件,事件注冊(cè)等等
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("MainActivity--onCreate");
}
}
Activity傳遞數(shù)據(jù)
在Android中,不同的Activity實(shí)例可能運(yùn)行在一個(gè)進(jìn)程中,也可能運(yùn)行在不同的進(jìn)程。因此我們需要一種特殊的機(jī)制,幫助我們?cè)贏ctivity之間傳遞消息。Android中通過Intent對(duì)象來表示一條消息,一個(gè)Intent消息不僅包含這個(gè)消息的目的地,還可以包含消息的內(nèi)容,這好比一封Email,其中不僅包含該手賤地址,還可以包含具體的內(nèi)容,對(duì)于一個(gè)Intent對(duì)象,消息“目的地”是必須的,而內(nèi)容則是可選項(xiàng)。
通過Intent來啟動(dòng)一個(gè)Activity
//通過反射機(jī)制,獲取字節(jié)碼
//創(chuàng)建意圖,參數(shù):上下文,要跳轉(zhuǎn)的組件的字節(jié)碼
Intent intent = new Intent(this,MainActivityB.class);
//啟動(dòng)一個(gè)Activity
startActivity(intent);
在上面的實(shí)例中通過Activity.StartActivity(intent)啟動(dòng)另外一個(gè)Activity的時(shí)候,我們?cè)贗ntent類的構(gòu)造器中指定了“收件人的地址”
**傳遞數(shù)據(jù)的兩種方式:
- 直接通過Bundle對(duì)象來傳遞:**
第一個(gè)Activity發(fā)送數(shù)據(jù)
//通過反射機(jī)制,獲取字節(jié)碼
//創(chuàng)建意圖,參數(shù):上下文,要跳轉(zhuǎn)的組件的字節(jié)碼
Intent intent = new Intent(this,MainActivityB.class);
//封裝要傳遞的數(shù)據(jù)
//通過Bundle傳遞數(shù)據(jù),是HashMap的一個(gè)封裝類
Bundle data = new Bundle();
data.putString("info",info);
//Bundle數(shù)據(jù)放入Intent
intent.putExtra("data",data);
第二個(gè)Activity接收數(shù)據(jù)
//獲取Intent,不是同一個(gè)Intent但是同樣的內(nèi)容
Intent intent = getIntent();
//獲取Bundle
Bundle data = intent.getBundleExtra("data");
//從Bundle中取數(shù)據(jù)
String info = data.getString("info");
2. 通過Intent定義的Bundle對(duì)象
第一個(gè)Activity發(fā)送數(shù)據(jù)
//通過反射機(jī)制,獲取字節(jié)碼
//創(chuàng)建意圖,參數(shù):上下文,要跳轉(zhuǎn)的組件的字節(jié)碼
Intent intent = new Intent(this,MainActivityB.class);
intent.putExtra("info",info);
第二個(gè)Activity接收數(shù)據(jù)
Intent intent = getIntent();
String info = intent.getStringExtra("info");
傳遞自定義的對(duì)象數(shù)據(jù)
方法一:序列化對(duì)象
自定義的對(duì)象,必須繼承接口Serializable
//序列化對(duì)象,通過I/O傳輸,存儲(chǔ)文件或者對(duì)象進(jìn)行傳輸。
//這里可能是兩個(gè)進(jìn)程傳數(shù)據(jù),相當(dāng)于通過網(wǎng)絡(luò)傳輸,需要序列化
public class Cat implements Serializable {
String name;
int age;
String type;
@Override
public String toString() {
return "Cat{" +
"age=" + age +
", name='" + name + '\'' +
", type='" + type + '\'' +
'}';
}
}
發(fā)送數(shù)據(jù)
public void sendObjClick(View v){
Cat cat = new Cat();
cat.name = "皮卡丘";
cat.age = 2;
cat.type = "中華田園貓";
Intent intent = new Intent(this,MainActivityB.class);
intent.putExtra("cat",cat);
startActivity(intent);
}
接收數(shù)據(jù)
Cat cat = (Cat) intent.getSerializableExtra("cat");
方法二:
使用java的序列化消耗太大,所以使用android自己的方法,繼承Parcelable接口。
下面是官方文檔的介紹和基本使用:
Interface for classes whose instances can be written to and restored from a Parcel. Classes implementing the Parcelable interface must also have a non-null static field called ==CREATOR== of a type that implements the Parcelable.Creator interface.
A typical implementation of Parcelable is:
public class MyParcelable implements Parcelable {
private int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in) {
mData = in.readInt();
}
}
自定義的對(duì)象
/**
* Created by TianMengmeng on 2018/6/6.
*/
public class Dog implements Parcelable{
String name;
int age;
String type;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
dest.writeString(type);
}
//對(duì)象的創(chuàng)建器,解包成要的對(duì)象
public static final Parcelable.Creator<Dog> CREATOR
= new Parcelable.Creator<Dog>() {
public Dog createFromParcel(Parcel in) {
Dog dog = new Dog();
//讀取對(duì)象內(nèi)容,需要和上面的寫的順序一致
dog.name = in.readString();
dog.age = in.readInt();
dog.type = in.readString();
return dog;
}
public Dog[] newArray(int size) {
return new Dog[size];
}
};
@Override
public String toString() {
return "Dog{" +
"age=" + age +
", name='" + name + '\'' +
", type='" + type + '\'' +
'}';
}
}
發(fā)送數(shù)據(jù):
Dog dog = new Dog();
dog.name="大黃";
dog.age = 1;
dog.type = "中華田園犬";
Intent intent = new Intent(this,MainActivityB.class);
intent.putExtra("dog",dog);
startActivity(intent);
接收數(shù)據(jù)
Dog dog = intent.getParcelableExtra("dog");
Activity處理返回結(jié)果
Android提供了一個(gè)機(jī)制,跳轉(zhuǎn)到其他Activity時(shí),在返回,可以接收到其他的activity返回的值,無需再start新的當(dāng)前activity值;
A發(fā)送數(shù)據(jù):startActivityForResult(intent, REQUESTCODE_1);
B接受數(shù)據(jù),設(shè)置返回結(jié)果:setResult(RESULT_OK,intent);
A重寫方法處理返回結(jié)果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUESTCODE_1 && resultCode == RESULT_OK){
String number = data.getStringExtra("number");
edittext.setText(number);
}
}
通過請(qǐng)求狀態(tài)碼和結(jié)果狀態(tài)碼,區(qū)分不同的結(jié)果
Activity運(yùn)行時(shí)屏幕方向與顯示方式
Android內(nèi)置了方向感應(yīng)器的支持。Android會(huì)根據(jù)所處的方向自動(dòng)在豎屏和橫屏之間切換。但是有時(shí)我們的程序僅僅能在橫屏和豎屏?xí)r運(yùn)行,比如某些游戲,此時(shí)我們需要鎖定該Activity運(yùn)行時(shí)的屏幕方向,Activity結(jié)點(diǎn)的android:screenOrientation屬性可以完成該項(xiàng)任務(wù)。
以下是一個(gè)示例:
修改manifes文件
<activity
android:name=".ScreenOrientstion"
android:label="@string/title_activity_screen_orientstion"
android:theme="@style/AppTheme.NoActionBar"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
代碼設(shè)置,需要在setContentView之前
public class ScreenOrientstion extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//設(shè)置豎屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
//設(shè)置全屏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
//去自己的標(biāo)題
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_screen_orientstion);
}
}
還可以設(shè)置窗體模式等。
Activity屏幕方向的旋轉(zhuǎn)
屏幕切換時(shí),會(huì)重新創(chuàng)建Activity,此時(shí)為了保存當(dāng)前的Activity的狀態(tài)。Activity狀態(tài)沒有保存,切換時(shí)會(huì)會(huì)調(diào)用onSaveInstanceState(Bundle outState),應(yīng)該重寫onSaveInstanceState(Bundle outState)方法,然后在onCreate中還原數(shù)據(jù)
重寫方法
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("index",index);
}
切換屏幕后會(huì)執(zhí)行onCreate方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_orientstion);
if(savedInstanceState != null){
index = savedInstanceState;
}
}
每次切換屏幕重新創(chuàng)建Activity會(huì)影響性能,可以在manifest文件中添加屬性android:configChanges="keyboard|orientation|screenSize",屏幕切換時(shí)調(diào)用onConfigurationChanged方法,使用了原來的Activity,不用保存對(duì)象了。此方法可以用來加載布局。
Activity通過SharePreference保存數(shù)據(jù)
不想寫了。。。