Android開發四大組件之Activity
android開發的四大組件分別是:Activity(活動),活動,與用戶交互界面; Service(服務),後臺運行服務,不提供界面呈現;Content Provider(內容提供器),實現應用之間的數據共享;Broadcast Receiver(廣播),爲了進行系統級別的消息通知,引入廣播消息機制,應用程序可以對感興趣的廣播進行註冊接收相關廣播類。今天講解的是Activity。
GitHub
:源碼
名詞解釋
- Activity:活動,與用戶交互界面,上面放置佈局和UI控件
- Layout:佈局,上面放置UI控件
- 控件:是編程中使用的,比如按鈕、窗口等都是控件
介紹幾款常用控件:
TextView 顯示文字,相當於Panel
ImageView 顯示圖片
EditText 輸入框,可編輯,可設置軟鍵盤方式
Button 按鈕,可附帶圖片
CheckBox 複選框
RadioButton 單選按鈕(和RadioGroup配合使用)
三者之間的關係如下圖所示:
每個Activity相當於一個頁面,一個android程序由多個Activity組成。在android開發中,Activity的生命週期起到了非常重要的作用。Activity生命週期如下圖所示:
新建Activity
1、首先需要確定,在那個路徑下新建Activity。
2、右鍵->“New”->“Activity”->“Empty Activity”
3、配置Activity
PS:較新版本默認是勾選“Generate Layout File”。如果你用的是較老版本的Android Studio,則需要自己串講Layout佈局文件,然後和Activity關聯起來,,較老版本的Activity創建之後還需要註冊。
當然較新版本都是自動完成的。雖然說大部分軟件老版本穩定一些,有些人喜歡用老版本,但也沒有必要用太老的版本。推薦大家用Android Studio3.3及以後的版本。
4、點擊“Finish”之後就可以看到,新建的Activity和自動生成的layout佈局文件了。layout佈局文件在res/layout下面。
Activity之間的跳轉
activity之間的跳轉分爲顯式跳轉和隱式跳轉。
顯式跳轉
優點
- 性能高
- 可讀性強
- 目標 Activity 唯一
缺點
- 產生強耦合
- 目標 Activity 寫死,不夠靈活
隱式跳轉
優點
- 避免了強耦合
- 可由後端以字符串形式吐出,靈活可配,比如目標 Activity 出現嚴重故障,通過後端吐空來規避故障
缺點
- 同一個 scheme 對應多個 Activity 時,跳轉時目標 Activity 不唯一,即使多個 Activity 分佈於多個應用中
- 由於跳轉不顯示引用目標Activity,當目標Activity被誤刪時無法靜態檢查跳轉異常,從而留下隱患,可能導致線上crash,需要在跳轉處加try-catch保證健壯性
實例
在AndroidManifest.xml中修改以下配置
<activity android:name=".Main2Activity"> //name必須和要跳轉到的Activity的名字相同
<intent-filter>
<action android:name="abc" /> //name隨意取
<category android:name="def" />
<category android:name="android.intent.category.DEFAULT" /> //必須要有這一條
</intent-filter>
</activity>
在MainActivity的佈局文件activity_main.xml中添加一個Button控件。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跳轉到第二個Activity"
android:textSize="25dp"
android:textColor="#111">
</TextView>
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="顯式跳轉" />
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="隱式跳轉" />
<Button
android:id="@+id/btn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="隱式跳轉百度" />
</LinearLayout>
然後,在Main2Activity的佈局文件activity_main2.xml中添加一個Text控件。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Main2Activity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="這是第二個Activity"
android:textColor="#111"
android:textSize="25dp"></TextView>
</LinearLayout>
最後在MainActivity中根據id獲取button控件並且添加點擊監聽
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//顯式跳轉
Button btn = findViewById(R.id.btn);//根據id獲取button按鈕
btn.setOnClickListener(new View.OnClickListener() {//對button按鈕設置點擊監聽
@Override
public void onClick(View v) {//當點擊button按鈕時跳轉頁面
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
startActivity(intent);//啓動Activity
}
});
//隱式跳轉
Button btn2 = findViewById(R.id.btn2);
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("abc"); //匹配action的name
intent.addCategory("def");//匹配除了默認category以外的category名
startActivity(intent);
}
});
/**
* 敲黑板,劃重點
* 根據隱式跳轉的優缺點可以看出,隱式跳轉一般不適用於activity之間的跳轉
* 隱式跳轉多用於打開內置(如瀏覽器等)
*/
Button btn3 = findViewById(R.id.btn3);
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
/**
* 用於顯示用戶的數據。比較通用,會根據用戶的數據類型打開相應的Activity。
* 比如tel:13400010001打開撥號程序,http://www.baidu.com則會打開瀏覽器
*/
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});
}
連接模擬器並運行程序,效果圖下所示:
Activity之間的數據傳遞
Activity之間傳遞數據使用Intent對象
傳遞基本數據類型
傳遞方
Intent intent = new Intent();
//name是一個唯一標識,可以隨便命名,value就是要觸底的數據
intent.putExtra("name", "value");
startActivity(intent);
接收方
Intent intent = getIntent();
String who = intent.getStringExtra("who");//根據傳遞的數據類型來定
傳遞對象
在Activity之間傳遞對象,這個對象須是可以序列化的
,傳遞對象可以通過下面幾種方式實現:
1、類實現Serializable,Java提供的序列化的接口
2、類實現Parcelable,Android提供的在移動端的序列化接口,效率更高
那是不是Parcelable接口效率更高,就不使用Serializable了呢?
答案肯定是否定的,要根據情況而定
1、Parcelable不能使用將數據存儲在磁盤上,因爲Parcelable在外界有變化的情況下不能很好的保存數據的持續性。因此在這種情況下,建議使用Serializable。
2、在使用內存的時候,Parcelable比Serializable性能高,所以推薦使用Parcelable類。並且Serializable在序列化的時候會產生大量的臨時變量,從而引起頻繁的GC。
實例
在activity_main2.xml中添加一個按鈕,用來舔磚到Main3Activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".Main2Activity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="這是第二個Activity"
android:textColor="#111"
android:textSize="25dp"></TextView>
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="攜帶數據跳轉">
</Button>
</LinearLayout>
Main2Activity如下所示:
public class Main2Activity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Button btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Main2Activity.this, Main3Activity.class);
intent.putExtra("who", "Me");
intent.putExtra("person", new Person("張三", 21, "三里屯"));
startActivity(intent);
}
});
}
}
/**
* 敲黑板,劃重點
* intent要傳遞對象有以下兩種方法
* 1、類實現Serializable,Java提供的序列化的接口
* 2、類實現Parcelable,Android提供的在移動端的序列化接口,效率更高
*/
class Person implements Serializable {
String name; //姓名
int age; //年齡
String addr; //住址
public Person(String name, int age, String addr) {
this.name = name;
this.age = age;
this.addr = addr;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", addr='" + addr + '\'' +
'}';
}
}
在Main3Activity中接收數據
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
TextView text = findViewById(R.id.text1);//根據id獲取文本控件
Intent intent = getIntent();
String who = intent.getStringExtra("who");//根據傳遞的數據類型來定
Person person = (Person) intent.getExtras().getSerializable("person");
text.setTextColor(0xffff3030);//設置字體顏色
text.setText("who:" + who + ",\nperson:" + person);//設置文字內容
}
activity_main3.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Main3Activity">
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25dp"></TextView>
</LinearLayout>
效果圖如下: