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>
效果图如下: