一、活动的基本用法
1.手动创建活动
点击项目包—>New—>Activity—>Empty Activity
创建活动时弹出对话框的三个选项:
- Generate Layout File:为当前活动创建一个对应的布局文件。
- Launcher Activity:自动将该活动设置为当前项目的主活动。
- Backwards Compatibility:为项目启动向下兼容的模式。
2.创建活动的过程
(1)创建布局
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 1"/>
</LinearLayout>
android:id:给当前的元素定义一个唯一的标识符
值:
- 在XML中定义一个id:@+id/id_name
- 在XML中引用一个id:@id/id_name
android:layout_width:指定当前元素的宽度
android:layout_height:指定当前元素的高度
值:
- match_parent:表示当前元素的宽/高与父元素一样宽/高
- wrap_contenr:表示当前元素的宽/高刚好能包含里面的内容
(2)加载布局
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
setContentView():给当前的活动加载一个布局。传入一个布局文件的id
(3)AndroidManifest中注册活动
所有活动需要在AndroidManifest中注册才能生效,活动会自动进行注册
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
引入主活动:
在<activity>
标签内部加入<intent-filter>
标签
android:name:指定注册哪一个活动
值:.类名
android:label:指定活动中标题栏的内容
二、Toast的使用
Toast:一种提醒方式,可通知一些短小消息,并在一段时间后自动消失
通过点击按钮弹出提示信息。布局文件如上
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"You clicker Button1",Toast.LENGTH_SHORT).show();
}
});
}
方法解析:
findViewById():获取布局文件中定义的元素,返回值为View
传入:R.id.id名称
setOnClickListener():为按钮注册一个监听器,点击按钮就会执行监听器中的onClick()方法
makeText():创建Toast对象
- 第一个参数:context:表示上下文,直接传入活动名.this
- 第二个参数:Toast显示的文本内容
- 第三个参数:Toast显式的时长。包含常量Toast.LENGTH_SHORT和Toast.LENGTH_LONG
show():显示Toast
三、Menu的使用
1.创建布局文件
在res中新建menu文件夹,在该文件夹下建菜单文件main.xml
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/add_item"
android:title="add"/>
<item
android:id="@+id/remove_item"
android:title="remove"/>
</menu>
<item>
:创建具体的某一个菜单项
android:title:给菜单项指定名称
2.在活动中显示菜单
Activity.java
为当前活动创建菜单:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//给menu菜单加载布局
getMenuInflater().inflate(R.menu.main,menu);
//显示菜单
return true;
}
方法解析:
onCreateOptionsMenu(Menu menu):初始化选项菜单
参数:要显示的menu实例
返回值:
- true:允许创建的菜单显示出来
- false:不显示创建的菜单
getMenuInflater():得到MenuInflater对象。
MenuInflater对象:加载menu布局文件的。
inflate(int menuRes, Menu menu)::用于找出menu布局文件
- 第一个参数:指定通过哪一个资源文件创建菜单
- 第二个参数:指定菜单项添加到哪一个Menu对象中
-----------------------------------------------------------------------------------------------------------------------------
inflate、setContentView、findViewById的区别
- inflate:实例化布局文件。找出xml中定义的一个Layout,并转换成View类型的对象。
如果一个布局文件中定义了好几个Layout,想要在活动中设置其中一个对话框Layout的组件的内容。
需要先通过inflate方法取得该layout,在通过findViewById获取该layout中需要修改的的组件
View view1=View.inflate(this,R.layout.dialog_layout,null);
TextView dialogTV=(TextView)view1.findViewById(R.id.dialog_tv);
dialogTV.setText("abcd");
- setContentView:用于给活动加载一个布局,使当前活动显示出界面
- findViewById:用于得到布局中的控件
-------------------------------------------------------------------------------------------------------------------------------
3.定义菜单响应事件
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch(item.getItemId()){
case R.id.add_item:
Toast.makeText(this,"You clicked Add",Toast.LENGTH_SHORT).show();
break;
case R.id.remove_item:
Toast.makeText(this,"You clicked remove",Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
方法解析:
onOptionsItemSelected(MenuItem item):点击菜单项响应事件的方法
getItemId():得到菜单项id
点击
点击菜单项弹出提示:
四、销毁活动
点击按钮销毁当前活动,效果与退出活动一样
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
finish():销毁当前活动
五、Intent
Intent:Android中各组件进行交互的一种重要方式
1.显式Intent
通过点击button1按钮,从MainActivity活动跳转到SecondActivity活动
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//在MainActivity活动中打开SecondActivity活动
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
});
方法解析:
Intent(Context packageContext, Class<?> cls)
- 第一个参数:启动活动的上下文 。即当前活动
- 第二个参数:指定想要启动的目标活动
startActivity():启动活动
2.隐式Intent
在AndroidMainfest.xml的application标签中添加如下内容:
<activity
android:name=".SecondActivity"
android:exported="true">
<intent-filter>
<!--指定当前活动能响应的action和category-->
<action android:name="com.example.activitytest.ACTION_START" />
<!--默认值-->
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
MainActivity
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//启动能响应的活动的action为com.example.activitytest.ACTION_START的活动
Intent intent = new Intent("com.example.activitytest.ACTION_START");
startActivity(intent);
}
});
<action>
和<category>
中的内容能同时匹配FirstActivity的Intent中指定的action和category时,SecondActivity活动才能响应Intent。
3.Intent的更多用法
(1)向下一个活动传递数据
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
...
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String data = "hello";
Intent intent = new Intent(MainActivity.this,FirstActivity.class);
//向intent中存入数据
intent.putExtra("extra_data",data);
startActivity(intent);
}
});
}
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("FirstActivity",data);
}
}
方法解析:
putExtra(String name, @Nullable String value) :用于存数据。以键值对方式存储
- 第一个参数:键
- 第二个参数:真正要传递的数据
getIntent():获取到启动该Activity的Intent
getStringExtra(String name):获取intent传递过来的数据。参数为putExtra()的键名
根据数据类型还有getIntExtra、getByteExtra等
(2)返回数据给上一个活动
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button)findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,FirstActivity.class);
//启动活动
startActivityForResult(intent,1);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (resultCode) {
case 1:
//判断处理结果
if (resultCode == RESULT_OK) {
String returnData = data.getStringExtra("extra_data");
Log.d("FirstActivity", returnData);
}
break;
default:
}
}
}
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
Intent intent = new Intent();
intent.putExtra("extra_data","Lily");
//向上一个活动返回数据
setResult(RESULT_OK,intent);
//销毁活动
finish();
}
}
方法解析:
startActivityForResult(Intent intent,int requestCode):启动活动,但该方法在活动销毁时能返回一个结果给上一个活动。
- 第二个参数:请求码。请求码只要是唯一值就可。
setResult(int resultCode, Intent data) :用于向上一个活动返回数据
- 第一个参数:用于向上一个活动返回处理结果 。一般使用RESULT_OK或RESULT_CANCELED
- 第二个参数:Intent对象
onActivityResult(int requestCode, int resultCode, @Nullable Intent data):活动销毁之前会回调上一个活动的该方法。通过该方法得到返回数据
- 第一个参数:启动活动时传入的请求码
- 第二个参数:返回活动时传入的处理结果
- 第三个参数:携带返回数据的intent
因为在一个活动中可能会调用startActivityForResult()方法启动很多不同的活动,每个活动的返回数据都会回调到onActivityResult()方法中。所以通过检查requestCode的值判断数据来源。
确定是从哪个活动返回的数据,再通过resultCode的值判断处理结果是否成功。成功就取出第三个参数的值
(3)启动其他程序的活动
Intent可在当前活动中打开一个网页或打开拨号界面
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});
Button button2 = (Button)findViewById(R.id.button2);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_DIAL);
//tel表示协议
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
});
}
}
可不在清单文件给FirstActivity里添加<intent-filter>
。不添加就直接打开百度网页
AndroidManifest.xml:
<activity android:name=".FirstActivity"
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"/>
</intent-filter>
MainActivity中Intent的action与FirstActivity的中配置的action值一样。且协议为http,所以点击按钮跳转到的页面会弹出一个列表,列表中有Browser和ActivityTest,选择Browser打开百度网页,选ActivityTest打开FirstActivity
方法解析:
Android内置action:
Intent.ACTION_DIAL:调用系统拨号界面
Intent.ACTION_VIEW:打开一个新页面
Uri.prase(String uriString):将字符串解析成一个Uri对象
setData(Uri data):用于指定intent要操作的URI对象。<data>
:指定当前活动响应什么类型的数据
属性:
- android:scheme:指定数据的协议部分
- android:host:指定数据的主机名部分
六.活动的生命周期
1.返回栈
- Android使用Task来管理活动,一个Task就是一组存放在栈里的活动的集合。这个栈就是返回栈。
- 每当启动一个新活动时,该活动会在返回栈中入栈,并处于栈顶的位置。当按Back键返回或调用finish()方法销毁活动时,处于栈顶的活动会出栈。
- 系统总是给用户显示处于栈顶的活动。
2.活动状态
(1).运行状态
当一个活动处于返回栈的栈顶时,该活动就处于运行状态
(2)暂停状态
当一个活动不再处于栈顶位置,但仍然可见,活动就进入了暂停状态
(3)停止状态
当一个活动不再处于栈顶位置,且完全不可见,活动就进入了停止状态
(4)销毁状态
当一个活动从返回栈中移除后就变成了销毁状态
3.活动的生命周期
onCreate():创建活动时被调用。在此方法中完成活动的初始化(加载布局、绑定事件),此时活动是不可见的。
onStart():启动活动时被调用,活动由不可见变为可见。但此时活动不能与用户进行交互
onResume():此时活动能与用户进行交互,且活动位于栈顶
onPause():系统启动或恢复另一个活动时调用
onStop():停止活动时被调用
onDestroy():销毁活动时被调用
onRestart():重启活动时被调用,活动由停止状态变为运行状态
活动生命周期例子:
在主活动中设置两个按钮,点击第一个按钮启动一个普通活动,点击第二个按钮启动一个对话框活动。
<activity
android:name=".DialogActivity"
<!--设置当前活动的主题是对话框-->
android:theme="@android:style/Theme.Dialog">
</activity>
</application>
android:theme:该属性用于给当前活动设置主题
@android:style:引入主题样式
@Override
protected void onCreate(Bundle savedInstanceState) {
...
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,NormalActivity.class);
startActivity(intent);
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,DialogActivity.class);
startActivity(intent);
}
});
@Override
protected void onStart() {
super.onStart();
Log.d(TAG,"onStart");
}
//此处省略其余六种方法
}
MainActivity第一次被创建时:
依次执行onCreate()、onStart()、onResume()
点击button1启动NormalActivity活动:
是启动了一个新活动,执行:onPause()、onStop()
NormalActivity活动完全覆盖了MainActivity活动,所以会执行onStop(),MainActivity活动进入停止状态
按下Back键返回MainActivity:
MainActivity被重新启动,执行:onRestart()、onStart()、onResume()
点击button2启动DialogActivity活动:
执行:onPause()
不执行onStop()是因为DialogActivity活动是弹出一个对话框,没有完全覆盖MainActivity活动。所以MainActivity只是进入暂停状态,没有进入停止状态。
按下Back键返回MainActivity活动:
执行onResume()
MainActivity之前只是进入了暂停状态,不需要重启
按退出键返回程序:
执行onPause()、onStop()、onDestory()
4.活动被回收怎么办
当系统内存不足时,处于停止状态的活动有可能被回收。则活动中所存的临时数据会没有了。
通过onSaveInstanceState()方法可解决该问题。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState!=null){
//取出数据
String data = savedInstanceState.getString("name");
Log.d("MainActivity",data);
}
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
String data = "Lily";
//存入数据
outState.putString("name",data);
}
}
方法解析:
onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState):活动被回收之前会回调该方法。可将数据保存在Bundle类型的参数中。活动即使被回收,也能将数据保存下来。
活动在被回收之前通过onSaveInstanceState()方法保存数据,则onCreate()方法中的savedInstanceState参数存有之前保存的全部数据。
执行onSaveInstanceState()方法的情况:
1、当用户按下HOME键时
2、长按HOME键,选择运行其他的程序时
3、按下电源按键(关闭屏幕显示)时
4、从activityA中启动一个新的activity时
5、屏幕方向切换时,例如从竖屏切换到横屏时
注意:按Back键不会执行onSaveInstanceState()方法。
七.活动的启动方式
standard:活动默认的启动模式
不管活动是否在返回栈中,每次启动活动都会创建该活动的一个新的实例(即:每次启动都要执行onCreate()方法)
singleTop:
启动活动时,如果该活动正好位于返回栈的栈顶,直接使用它,不会再创建新的活动实例。
singleTask:
每次启动活动在返回栈中检查是否存在该活动。存在就直接使用该实例,并把这个活动之上的所有活动统统出栈。不存在就创建一个新的活动实例。
singleInstance:
指定为singleInstance的活动会启动一个新的返回栈来管理这个活动。
实例:
1、启动模式为singleTop:
Manifest中添加启动模式代码
<activity
android:name=".FirstActivity"
android:launchMode="singleTop"
android:exported="true" />
android:launchMode:用于设置android启动模式
MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG="MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//this指当前活动
Log.d("MainActivity",this.toString());
setContentView(R.layout.activity_main);
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, FirstActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG,"M:onStart");
}
//OnPause()等方法省略
}
toString():返回当前Activity的name+“@”+当前object的索引。
FirstActivity
public class FirstActivity extends AppCompatActivity {
private static final String TAG="FirstActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FirstActivity",this.toString());
setContentView(R.layout.activity_first);
Button button2 = (Button)findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(FirstActivity.this, MainActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG,"F:onStart");
}
//OnPause()等方法省略
}
运行结果:
启动活动:
com.example.activitytest.MainActivity@cfbd3a2、M:onStart、M:onResume
点击button1:
M:onPause、com.example.activitytest.FirstActivity@3a0ef58、F:onStart、F:onResume、M:onStop
点击button2:
F:onPause、com.example.activitytest.MainActivity@8eeee30、 M:onStart、M:onResume、F:onStop
因为在FirstActivity中再次启动MainActivity活动时,处于栈顶的活动是FirstActivity。所以会创建MainActivity实例
2、启动模式为singleTask:
再次启动MainActivity活动时,不会创建实例。其他执行结果与上面相同。
3、启动模式为singleInstance:
<activity
android:name=".FirstActivity"
android:exported="true"
android:launchMode="singleInstance" />
MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("MainActivity","Task id is"+getTaskId());
...
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, FirstActivity.class);
startActivity(intent);
}
});
}
//OnStart()等方法省略
}
getTaskId():得到当前返回栈的id值
FirstActivity.java代码将上述代码修改为:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
SecondActivity不添加点击事件,其余与上述代码相同。
运行结果:
启动活动:
Task id is54、 M:onStart、M:onResume
点击button1:
M:onPause、Task id is55、F:onStart、F:onResume、M:onStop
点击button2:
F:onPause、Task id is54、S:onStart、S:onResume、F:onStop
点击Back键返回:返回到MainActivity界面
M:onRestart、M:onStart、 M:onResume
FirstActivity放在一个单独的返回栈里。MainActivity和SecondActivity放在一个单独的栈里。
SecondActivity页面点击Back键返回,则SecondActivity从栈中出去,该栈中MainActivity成为栈顶活动显示到页面上。
再次点击Back键返回:返回到FirstActivity界面
F:onRestart、 F:onStart、 F:onResume
上个步骤后,MainActivity和FirstActivity所在返回栈已为空。所以点击Back键会显示另一个返回栈的栈顶活动。
再次点击Back键返回:退出程序
M:onPause、M:onStop、M:onDestroy
所有返回栈为空,退出程序