探究活动
活动的基本用法
创建活动
首先创建一个空项目,右击com.example.activitytest包→New→Activity→Empty Activity,弹出一个创建活动的对话框。将活动命名,并且不要勾选Generate Layout File和Launcher Activity
创建任何活动都应该重写onCreate()
方法,Android Studio已经自动重写好。
创建和加载布局
右击app/src/main/res目录→New→Directory会弹出一个目录窗口,创建一个layout目录,然后对着layout右键→Newyou→Layout resource file会弹出新建布局资源文件的窗口,我们命名为first_layout,根元素默认LinearLayout,这时就会看到布局编辑器。
我们在这里添加一个按钮
<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/button_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 1"/>
</LinearLayout>
预览结果如下
这里添加了一个Button元素,并且添加了几个元素,android:id
是给当前的元素定义一个唯一的标识符,之后可以在代码中对该元素操作。XML定义使用@id/id_name
的语法。
接下来就要在在活动中加载这个布局,回到FirstActivity,在OnCreate()中加入代码
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_layout);
}
}
在AndroidMainfest文件中注册
活动声明要放在<application>
标签内,这里是通过<activity>
标签来对活动进行注册的,在<activity>
标签内我们使用了android:name
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Activitytest">
<activity android:name=".FirstActivity"></activity>
</application>
在<activity>
内部添加<intent-filter>
标签,除此之外,我们还可以使用android:label
指定活动中标题栏的内容
<activity
android:name=".FirstActivity"
android:label="This is FirstActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
标题栏下面就是在布局文件first_layout.xml中编写界面
活动中使用Toast
Toast是系统提供的一种提醒方式,这些信息提醒一段时间后就会消失。
首先要定义一个弹出Toast的触发点,利用之前建立好的按钮来创立。
在onCreate()
中添加如下代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_layout);
Button button1 = (Button) findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Toast.makeText(FirstActivity.this,"You clicked Button 1",
Toast.LENGTH_SHORT).show();
}
});
}
在活动中,通过findViewById()
方法获取到在布局文件中定义的元素,这里我们传入R.id.button_1
,来获得按钮实例,这个值是刚才在first_ layout.xml
中通过android:id
属性指定的。findViewById()
方法返回的是一个View
对象,我们需要向下转型将它转成Button对象。得到按钮的实例之后,我们通过调用setOnClickListener()
方法为按钮注册一个 监听器,点击按钮时就会执行监听器中的onClick()
方法。因此,弹出Toast的功能当然是要在onClick()
方法中编写了。
Toast
的用法非常简单,通过静态方法makeText()
创建出一个Toast对象,然后调用show()
将Toast显示出来就可以了。这里需要注意的是,makeText()方法需要传入3个参数。第一个参数是Context
,也就是Toast要求的上下文,由于活动本身就是一个Context对象,因此这里直接传人FirstActivity. this
即可。第二个参数是Toast显示的文本内容,第三个参数是Toast 显示的时长,有两个内置常量可以选择Toast. LENGTH SHORT
和Toast. LENGTH LONG
。
在活动中使用Menu
首先在res目录下新建一个menu文件夹,右击res目录→New→Directory, 输人文件夹名menu, 点击OK。接着在这个文件夹下再新建一个名叫main的菜单文件,右击menu 文件夹→New →Menu resource file
然后再main.xml
中添加如下代码
<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:id
给这个菜单项指定一个唯一的标识符,通过android:title
给这个菜单项指定一个名称。
重写onCreateOptionMenu()
方法
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main,menu);
return true;
}
通过getMenuInflater()
方法能够得到MenuInflater对象,再调用它的inflate()
方法就可以给当前活动创建菜单了。inflate()
方法接收两个参数,第一个参数用于指定我们通过哪一个资源文件来创建菜单,这里当然传入R. menu . main
。第二个参数用于指定我们的菜单项将添加到哪一个Menu对象当中,这里直接使用onCreateOptionsMenu( )
方法中传人的menu参数。然后给这个方法返回true,表示允许创建的菜单显示出来,如果返回了false, 创建的菜单将无法显示。
再定义菜单响应事件
@Override
public boolean onOptionsItemSelected(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()
方法中,通过调用item. getItemId( )
来判断我们点击的是哪一个菜单项,然后给每个菜单项加人自己的逻辑处理,这里我们就活学活用,弹出一个刚刚学会的Toast
使用Intent在活动间穿梭
Intent可以实现在两个不同活动之间跳转
显式Intent
1.获得Intent实例,例:Intent intent=new Intent(Context,Class(指定想要启动的目标活动))。
2.调用startActivity(Intent)方法启动目标活动。
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v){//显式Intent
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
}
这里的Context上下文可以理解为启动活动的一个环境。
SecondActivity界面
隐式Intent
用活动的配置信息来判断要启哪一个活动
1.给要启动的活动配置action
和category
信息。
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.example.activitytest.MY_CATEGORY" />
</intent-filter>
</activity>
2.获得Intent实例
3.调用intent.addCategory(String(category信息))
方法给Intent配置category信息。
4.调用startActivity(Intent)
方法启动活动。
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v){//隐式Intent
Intent intent = new Intent("com.example.activitytest.ACTION_START");
intent.addCategory("com.example.activitytest.MY_CATEGORY");
startActivity(intent);
}
});
注意:只有action于category信息同时匹配才会启动相应活动,每个活动只能配置一个action信息,但可以配置多个category信息。
向下活动传递数据
在启动活动的时候可以传递数据
1.调用putExtra()
方法
2.书写要传入的数据
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v){//向下传递字符串
String data ="Hello SecondActivity";
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("extra_data",data);
startActivity(intent);
}
});
3.在下一个活动中实例化Intent并调用getStringExtra()
方法,传入键值,即可得到数据
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);
}
打开logcat
查看信息
返回数据给上一个活动
1.调用startActivityForResult()
方法,用于启动活动的,但这个方法期望在活动销毁的时候能够返回一个结果给上一个活动。
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {//向上传递数据
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(intent, 1);
}
});
2.在下一个活动注册一个事件去实现该效果
3.调用setResult()
专门用于向上一个活动返回数据的
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Button button2 = (Button)findViewById(R.id.button_2);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);
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();
}
});
}
4.在第一个活动中,重写onActivityResult()
方法,通过检查requestCode的值来判断数据来源,再通过resultCode的值来判断处理结果是否成功,最后从打data中打印出来。
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
String returnedData = data.getStringExtra("data_return");
Log.d("FirstActivity", returnedData);
}
break;
default:
}
}
活动的生命周期
返回栈
Android是使用任务( Task)来管理活动的,一个任务就是一-组存放在栈里的活动的集
合,这个栈也被称作返回栈( Back Stack )。栈是一种后进先出的数据结构,在默认情况下,每当
我们启动了一个新的活动,它会在返回栈中人栈,并处于栈顶的位置。而每当我按下Back键
或调用finish()
方法去销毁一个活动时,处于栈顶的活动会出栈,这时前一个入栈的活动就会
重新处于栈顶的位置。系统总是会显示处于栈顶的活动给用户。
活动状态
每个活动在其生命周期中最多可能会有4个状态。
- 1.运行状态
当一个活动位于返回栈的栈顶时,这是活动就处于运行状态。 - 2.暂停状态
当一个活动不再处于栈顶位置,但仍然可见时,这时活动就会处于暂停状态。 - 3.停止状态
当一个活动不再处于栈顶位置,且完全不可见时,就进入了停止状态。 - 4.销毁状态
当一个活动自从返回栈中移除后就变成了销毁状态。
活动的生存期
onCreate()
第一次创建时候调用,在这个方法中完成活动的初始化操作,比如加载布局、绑定事件。onStart()
该方法在活动由不可见变为可见时调用。onResume()
该方法在活动准备与用户进行交互时调用,此时活动一定处于栈顶且处于运行状态。onPause()
该方法在系统准备去启动或恢复另一个活动时调用。该方法的执行速度一定要快,否则会影响到新栈顶活动的使用。onStop()
该方法在活动完全不可见时调用,与onPause()方法的区别在于,若启动的新活动是一个对话框活动,那么onPause()方法会得到执行,而onStop()方法并不会执行。onDestroy()
该方法会在活动销毁前执行,之后活动的状态就会变为销毁状态。onRestart()
该方法会在活动由停止状态变为运行状态之前调用,也会就是活动被重新启动了。
活动被回收了怎么办
如果一个活动进入了停止状态,那么该活动是有可能被系统回收的,因此可能会导致数据丢失。
1.重写onSaveInstanceState()
方法,该方法可以保证在活动被回收之前获得调用,可以在其中调用putString(键,值)
方法来保存数据。
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("data_key",tempData);//根据类型调用不同的方法
}
2.在活动的onCreate()
方法中调用getString(键)
方法取出数据进行恢复。
if(savedInstanceState!=null){
String name=savedInstanceState.getString("name");
}
活动的启动模式
活动共有4种启动模式,分别是standard,singleTop,singleTask,singleInstance,可以在AndroidManifest.xml中通过给< activity >
标签指定android:launchMode
属性来选择启动模式。
-
standard:
默认模式,每当启动一个新的活动,就会在返回栈中入栈,并处于栈顶位置。该模式下无论这个活动是否在返回栈中存在,每次启动都会创建该活动的新实例。
-
singleTop:
该模式下,每当启动一个新的活动,如果发现返回栈的栈顶已是该活动,则可以直接使用它而不会再创建新的实例。
-
singleTask:
该模式下,每当启动一个新的活动,系统首先会在返回栈中检查是否存在该活动的实例,若存在就直接使用,并让该活动之上的所有活动出栈,若不存在则创建新的实例。
-
singleInstance
该模式下的活动会启用一个新的返回栈来管理这个活动。这个模式解决了其它程序和我们的程序共享一个活动实例的问题。