一、活动的基本用法
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) {
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) {
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 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) {
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.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);
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参数存有之前保存的全部数据。
七.活动的启动方式
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);
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");
}
}
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");
}
}
运行结果: 启动活动: 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);
}
});
}
}
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
所有返回栈为空,退出程序
|