一.创建Activity
- action的作用
action是显示数据给用户.
action是包含了UI和UI动作的代码.比如跳转,按钮单击事件等等.
每个action都对应一个界面配置文件,布局文件存在res下面的layout目录下.
- onCreate代码
创建号action后,可以看到有个onCreate代码.这里面就是编写与UI交互的主要方法.
- 绑定UI配置
在onCreate代码里加入setContenView(R.layout.布局名称)
- action的注册
创建好action后,需要在AndroidManifest.xml注册.
android studio会自动注册.对于多个活动,我们还可以指定哪个activity作为首页活动.只需要在activity中加入如下代码,就可以首先启动.
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
- 在活动中查找UI元素
findViewById(R.id.button1)
二.销毁Activity
正常情况下,返回键就会销毁当前活动.
也可以使用finish()方法来销毁.比如在按钮单击事件中执行,当前活动会直接销毁,界面消失.
private Button btn1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1=findViewById(R.id.button);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
Log.d(this.getClass().getName(),"测试");
}
三.action使用menu菜单
- 创建菜单UI配置
在res目录下,创建menu文件夹,然后创建menu resource file文件.
在里面添加标签:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/add" android:title="add">
</item>
</menu>
- 关联菜单
然后重写action中的OncreateOptionsMenu()方法.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menus,menu);
return true;
}
- 给menu增加响应事件
重写 onOptionsItemSelected
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.addx:
Toast.makeText(this, "添加",Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
然后运行,在手机右上角就会出现三个点.点击就会打开菜单.
四.activity跳转(界面跳转)
- 使用显示Intent
点击按钮,由MainActivity跳转到MainActivityB.
btnB=findViewById(R.id.button3);
btnB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent it = new Intent(MainActivity.this,MainActivityB.class);
startActivity(it);
}
});
- 隐式Intent
隐式的Intent是指不明确指定哪个action,而是靠系统分析,找出合适的Activity.比如你的app拉起支付宝app.
如果action要接受隐式的Intent跳转,需要在androidManifest.xml中,声明可以接受Intent调用.
比如我们要跳转到MainActivityB,就需要在AndroidManifest.xml修改MainActivityB的声明.
<activity android:name=".MainActivityB">
<intent-filter>
<action android:name="com.example.test.action_start"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
action 是声明这个是可以被隐式调用的activity.
category 是对这action的分类说明.
- 打开浏览器
btn4 = findViewById(R.id.button4);
btn4.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent it = new Intent(Intent.ACTION_VIEW);
it.setData(Uri.parse("http://www.baidu.com"));
startActivity(it);
}
});
Intent.ACTION_VIEW是系统内部的通用action,对应的是"android.intent.action.VIEW",配合Uri可以打开不同app等.
//打开电话
it.setData(Uri.parse("tel: 10086"));
//打开邮件
it.setData(Uri.parse("mailto:uri"));
- action的数据类型
当用打开浏览器时,我希望我新创建的action也能和浏览器一样在可选择清单里,怎么办?
这个时候,就需要设置这个action的数据类型了.
创建一个action,增加一个data配置,action配置为"android.intent.action.VIEW",这样能响应Intent.ACTION_VIEW的设置,配置如下:
<activity android:name=".MainActivity3">
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"/>
</intent-filter>
</activity>
|数据类型|说明|
|android:scheme|数据协议|
|android:host|域名或主机,如www.baidu.com|
|android:port|数据端口|
|android:path|域名:端口之后的内容|
|android:mimeType|允许使用通配符处理的数据类型|
只有data的配置和intent携带的信息一致时,才会响应intent.
- category有什么用?
在配置隐式intent时,这个是声明是默认的intent,如果不配置,会直接响应,而不是出现在被拉起的清单中.
五.intent传递数据
- 传递基本数据类型的数据
通过putExtra可以将数据传递到下个intent,下个intent 使用getStringExtra()获取.
#传递数据
Intent intent= new Intent(Aacitivity.this,Bactivity.class)
String data="我是传递的数据!"
intent.putExtra("key",data)
#获取数据
Intent intent=getIntent();
data=intent.getStringExtra("key")
对于其他基本数据类型,有对应的get方法.
- 传递对象对象类型的数据
被传递的对象需要实现序列号接口.比如有如下简单的类:
public class Book implements Serializable{
private String title;
private int page;
public Book(){
title='我是一本书';
page=812;
}
public String getTitle(){
return title;
}
public int getPage(){
return page;
}
}
使用getSerializableExtra获取对象.
#传递数据
intent.putExtra("book",book);
#取数据
Book book=(Book)intent.getSerializableExtra("book");
- 返回数据给上个Action
在activity中,有个startActivityForResult方法也是用于启动action的.但这个方法销毁时,期望能返回一个结果给上个活动.
发起的intent使用startActivityForResult启动,并设置请求码为1
Intent it = new Intent(MainActivity1.this,MainActivity4.class);
startActivityForResult(it,1);
接受者,点击按钮返回数据:
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent it = new Intent();
it.putExtra("key","你好");
//一般设置RESULT_OK或者RESULT_CANCELED
setResult(RESULT_OK,it);
finish();
}
});
发起的intent,重写onActivityResult方法,获取数据:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//验证请求码1
switch (requestCode) {
case 1:
//验证返回码
if(resultCode==RESULT_OK){
Log.i("test",data.getStringExtra("key"));
}
break;
default:
}
}
六.action的生命周期
- action的存储
action通过intent在各个action之间跳转。返回就销毁当前的action。这个活动的是放在stack里的.stack是先进后出,后进先出的数据结构.
每次点击back时,调用finsh()销毁当前action.stack就把最top的action删除.
生命周期状态
- 运行状态:
当前活动的action.在stack的顶部.
- 暂停状态
当处于非活动,但是仍然可见时,属于活动状态,不在stack顶部.如非全屏的对话框形式的窗口.
如果不是极度缺少内存,一般系统不会销毁这种action.
- 停止状态
停止,并且不可见,不在staick顶部.一般不会被销毁,如果缺少内存,可能会被销毁.
- 销毁状态
从stack移除,就被销毁了.
生命周期的七个方法
- onCreate()
action初始方法,活动创建时,被调用.
- onStart()
活动有不可见转为可见时调用.
- onResume()
活动准备和用户交互时调用.此时,action处于stack栈顶.
- onPause()
系统准备启动或者恢复另外一个action时.一般会释放无关紧要的数据,保存重要数据.这里的代码执行要快,不然会导致拉起新action卡,导致体验下降.
- onStop()
action完全不可见时调用.如果启用的活动是对话框的话,此方法不会调用,但是onPause()会调用.
- onDestroy()
action销毁前会调用.
- onRestart()
活动停止状态转为运行状态是调用.
通过以上方法,可以看出
1.完整生命周期为onCreate()->onDestroy()之间
2.生存期为onStart()->onStop()之间
onstart()可以拉起前加载数据,onStop()释放数据.
3.前台生存期onResume()->onPause()
onResume()为准备交互,onPause()要恢复或者启动其他action前,要做的释放动作.
返回上个action,上个action以及被销毁怎么办?
如果我们有a->b,b进入不可见的停止状态,这时内存不足,系统把a给销毁了,所以b返回a,a是重写创建.如果我们从b->a发现之前录入的数据没了,体验非常不好.
我们可以在被销毁前,保存临时的用户数据.
- **销毁前被执行的onSaveInstanceState():
@Override
protected void onSaveInstanceState(Bundle outState){
super.onSaceInstanceState(outSate);
String tempData="临时的数据"
out.State.putString("key",tempdData)
}
现在只需要在onCreate()方法提取数据即可.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState!=null){
String temp= savedInstanceState.getString("key")
}
}
七.action的启动模式
action有四个启动模式.因为每次启动(非唤醒)都会创建一个Instance,所以模式区别是有几个instance.
模式有:standard singeltop singleTask singleInstance,可以在AndroidManifest.xml中,通过activity标签指定andrlid:launchMode属性来指定.
模式 | 实例数 | 存储变量 | 说明 |
---|---|---|---|
standard | 可n个 | 本程序stack | 默认模式,每次启动创建1个,不管当前action是否在栈顶 |
singleTop | 可n个 | 本程序stack | 如果action处于栈顶,直接使用不在创建 |
singleTask | 本程序1个 | 本程序stack | 如果发现栈内有该action,直接使用 |
singleInstance | 操作系统1个 | 操作系统共享栈 | 与操作系统的其他共享action共享一个stack,主用用于与其他app共享该action.为了防止不同的app拉起该action导致创建多个instance,所以共享一个stack,这样只会拉起一个 |
八.活动的最佳实践
定位当前是哪个活动
随着app的action增多,有时不知道到底是哪个action.可以使用继承方式,在action基类里打印具体的action的名字.
方法就是建立一个baseActivity继承AppCompatActivity.然后在onCreate里增加Log.d(“dd”,getClass().getSimpleName())
一键退除app
不可能一一退出所有的action.要一键退出,我们需要将action集中管理.
方法是建立一个action管理的class,里面使用List来进行管理action的清单,可以增加可以删除,也可以一次循环销毁所有action.
然后在baseActivity里的创建方法里,每次创建都将action加入进去.
然后重写基类的onDestroy()方法,在该方法执行时,调用action管理类的删除方法即可. 当要退出整个app时,直接调用action管理类的销毁方法即可.为保证完全退出,可以直接调用android.os.Process.killProcess(android.os.Process.myPid())
启动活动的最佳方法
活动之间跳转,需要创建intent,传递数据. 如果是自己开发的action,如何创建,别人不一定知道,所以最好自己创建,让别人传递创建的参数即可.
比如自己开发的一个action,名称叫Bactivity,实现一个创建action的方法,然后通过onCreate调用.如:
public static void actionStart(Contenxt,String 参数1,String 参数2){
Intent intent = new Intenet (contenxt,SecondActivity.class);
intent.putExtra("key",参数1)
intent.putExtra("key",参数2)
contenxt.startActivity(intent)
}
这时如果别人要启动你的Bactivity,直接调用你的这个方法即可:
Bactivity.actionStart(调用者的引用(xx.this),参数1,参数2)
这样别人就可以方便的拉起你的action了.