Activity活动
Activity基本用法
创建Activity流程
- 创建Activity
- 右击com.example.myfzhou.activitytest包–>New–>Activity–>Empty Activity(不勾选Generate Layout File);
- 重写Activity的onCreate()方法。
- 创建、加载layout
- 在res目录下新建一个名为layout的Directoy,在layout目录下创建一个Layout resource file,至此创建layout完成;
- 回到FirstActivity,在onCreate()方法中加载布局:
setContentView(R.layout.first_layout)
。
- 注册Activity(Activity一般是Android Studio自动创建)
- 活动的注册声明要放在
<application>
标签内;
android:name
:指定具体注册哪一个活动android:label
:指定活动中标题栏的内容
- 在
<Activity>
标签内部加入<intent-filter>
标签,为程序配置主活动;
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
- 活动的注册声明要放在
使用Toast
Button button1 = findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Button button1 = findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(FirstActivity.this, "You clicked Button 1",Toast.LENGTH_SHORT).show();
}
});
findViewById()
:获取得到在布局文件中定义的元素,返回一个View对象(Android Studio 3不用将返回的对象进行向下转型)。setOnClickListener()
:为Button注册一个监听器,点击Button时就会执行监听器中的onClick()方法。- Toast主要用法:
oast.makeText(Context context, CharSequence text, int duration).show()
- Context context参数:Toast要求的上下文,Activity本身就是一个Context对象
- CharSequence text参数:Toast显示的文本内容
- int duration参数:Toast显示的时长
使用menu
- 在res目录下新建一个menu文件夹;
- 在menu文件夹新建一个菜单文件(Menu resource file)
- 在菜单文件添加以下代码
<item
android:id="@+id/add_item"
android:title="Add" />
<item
android:id="@+id/remove_item"
android:title="Remove" />
android:id
:给菜单项指定一个唯一的标识符android:title
:给菜单项指定一个名称
- 在Activity中重写onCreateOptionsMenu(Menu menu)方法
getMenuInflater()
:得到MenuInflater对象inflate (int menuRes, Menu menu)
:给当前活动创建菜单- int menuRes参数:指定通过哪一个资源文件来创建菜单
- Menu menu参数:指定菜单项将添加到哪一个Menu对象中
- 该方法返回true表示允许创建的菜单显示出来
- 定义菜单响应事件,在Activity中重写onOptionsItemSelected(MenuItem item)方法
- 在Activity中重写onCreateOptionsMenu(Menu menu)方法
使用Intent
Intent时Android程序中各组件之间进行交互的一种重要方式,不仅可以知名当前组件想要执行的动作,还可以在不同组件之间互相传递数据。
使用显式Intent
使用
Intent(Context packageContext, Class<?> cls)
构造器实现:- 第一个参数Context要求提供一个启动活动的上下文
- 第二个参数Class则是指定想要启动的目标活动
创建用这个构造器Intent对象,并调用startActivity(Intent intent)方法执行Intent对象。
使用隐式Intent
- 配置AndroidManifest.xml,在
<activity>
标签下配置<intent-filter>
,指定当前活动能够响应的action和category,在AndroidManifest.xml的注册对应活动的标签下添加下面的代码:
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.example.myfzhou.activitytest.MY_CATEGORY" />
</intent-filter>
- 修改Activity中按钮的点击事件:
Intent intent = new Intent("com.example.activitytest.ACTION_START");
intent.addCategory("com.example.activitytest.MY_CATEGORY");
startActivity(intent);
- AndroidManifest.xml和Activity.java中的
<action>
标签和<category>
标签的内容需要一致 android.intent.category.DEFAULT
是一种默认的category。
更多隐式Intent的用法
- 打开浏览器,并转到相应的Uri
button1.setOnclickListener(new View.OnClickListener() {
@override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});
还可以在<intent-filter>
标签中再配置一个<data>
标签,用于更准确地指定当前能够响应什么类型的数据。
- android:scheme。用于指定数据的协议部分,如http部分。
- android:host。用于指定数据的主机名部分,如网址。
- android:port。用于指定数据的端口部分。
- android:path。用于指定主机名和端口之后的部分。
- android:mimeType。用于指定可以处理的数据类型,允许使用通配符的方式进行指定。
2. 调用系统拨号界面
button1.setOnclickListener(new View.OnClickListener() {
@override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
});
Intent传递数据
- 向下一个活动传递数据
- 使用Intent提供的一系列
putExtra()
方法,把想要传递的数据暂时存放在Intent中,启动了另一个活动后,只需要把这些数据再从Intent中取出来就可以了。 - 存放数据到Intent
String data = "Hello SecondActivity";
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("extra_data", data);
startActivity(intent);
- 在另一个活动中取出Intent中的数据
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity", data);
- 使用Intent提供的一系列
- 返回数据给上一个活动
- 使用
startActivityForResult(Intent intent, int requestCode);
方法启动活动,期望在活动销毁的时候能够返回一个结果给上一个活动
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(intent, 1);
- 设置发送Intent数据
Button button2 = findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("data_return","Hello FirstActivity");
setResult(RESULT_OK, intent);
finish();
}
});
- 设置接受Intent数据
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 1:
if(resultCode == RESULT_OK) {
String returnedDATA = data.getStringExtra("data_return");
Log.d("FirstActivity",returnedDATA);
}
break;
default:
}
}
- 使用
活动的生命周期
返回栈
Android是使用任务(Task)来管理活动的。启动一个新的活动,它会在返回栈中入栈,并处于栈顶位置。销毁一个活动时,处于站定的活动会出栈,这时前一个入栈的活动就会重新处于栈顶的位置。系统总是会显示处于栈顶的活动给用户。
活动状态
- 运行状态:活动位于栈顶位置
- 暂停状态:不再处于栈顶位置,但仍然可见
- 停止状态:不再处于栈顶位置,并且完全不可见
- 销毁状态:从返回栈中移除后
活动的生存期
Activity类中定义的7个回调方法,覆盖了活动生命周期的每一个环节。
1. onCreate()
:每个活动中都重写的方法,在活动第一次被创建时候调用,在这个方法中完成活动的初始化操作;
2. onStart()
:在活动由不可见变为可见的时候调用;
3. onResume()
:在活动准备好和用户进行交互的时候调用,此时的活动一定位于返回栈的栈顶,并且处于运行状态;
4. onPause()
:在系统准备去启动或恢复另一个活动的时候调用,onPause()
方法是暂停状态,一般用于将消耗CPU的资源释放、保存一些关键数据,此方法执行速度要快;
5. onStop()
:在活动完全不可见的时候调用,即停止状态;
6. onDestroy()
:在活动被销毁之前调用,之后活动的状态将变为销毁状态;
7. onRestart()
:在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了。
活动的3种生存期
1. 完整生存期:onCreate()–>onDestroy()
2. 可见生存期:onStart()–>onStop(),此时活动对于用户总是可见的,即便有可能不能进行交互。
3. 前台生存期:onResume()–onPause(),此时活动总是处于运行状态,活动是可以和用户进行交互的。
活动的启动模式
启动模式一共有4种,分别是:standard、singleTop、singleTask、singleInstance,可以在AndroidManifest.xml中通过给<activity>
标签指定android:lauchMode
属性,来选择启动模式。
standard模式
standard是活动默认的启动模式,在不进行显式指定的情况下,所有活动都会自动使用这个启动模式。在standard模式下,每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶位置。系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。standard模式的原理图:
singleTop模式
当活动的启动模式指定为singleTop,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。但活动未处于栈顶位置时,再启动活动,还是会创建新的实例。
singleTask模式
每次启动该活动时,系统首先会再返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把再这个活动之上的所有活动统统出栈,如果没有返现就会创建一个新的活动实例。
singleInstance模式
singleInstance模式的活动会启用一个新的返回栈来管理这个活动,在这个模式下会有一个单独的返回栈来管理这个活动,不管是哪个应用程序来访问这个活动,都共用同一个返回栈。
活动的最佳实践
知晓当前是在哪一个活动
- 新建一个BaseActivity类,继承AppCompatActivity类,重写onCreate()方法
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("BaseActivity", getClass().getSimpleName());
}
}
- 活动都继承自BaseActivity类
随时退出程序
启动了多个活动后,退出程序是非常不方便的。
1. 用一个专门的集合类对所有的活动进行管理即可
public class ActivityCollector {
public static List<Activity> activities = new ArrayList<>();
public static void addActivity(Activity activity) {
activities.add(activity);
}
public static void removeActivity(Activity activity) {
activities.remove(activity);
}
public static void finishAll() {
for (Activity activity : activities) {
if(!activity.isFinishing()) {
activity.finish();
}
}
activities.clear();
}
}
- 在BaseActivity类中调用ActivityCollector的addActivity()把正在创建的活动添加到活动管理器里,在BaseActivity中重写onDestroy()方法,并调用ActivityCollector的removeActivity()方法,将一个马上要销毁的活动从活动管理器里移除。
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("BaseActivity", getClass().getSimpleName());
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
}
- 在需要退出程序的活动中,调用
ActivityCollector.finishAll()
方法就可以了。
启动活动的最佳写法
- 在活动中添加一个actionStart()方法,在这个方法中完成Intent的构建,所有活动中需要的数据都通过这个方法的参数传递,把数据存到Intent中。
- 调用startActivity()方法启动活动。
public static void actionStart(Context context, String data1, String data2) {
Intent intent = new Intent(context,SecondActivity.class);
intent.putExtra("param1", data1);
intent.putExtra("param2", data2);
context.startActivity(intent);
}
- 在其他活动中,可以简化启动活动的代码。
button1.setOnClickListener(new OnClickListener() {
@override
public void onClick(View v) {
SecondActivity.actionStart(FirstActivity.this, "data1", "data2");
}
});