Activity是Android的门面,可以与用户进行互动的重要模块,凡是在应用中可以看到的东西,都是放在活动中的。
在学习新的技术时,我喜欢将需要学习的技术与自己懂得技术进行类似比较,而活动(Activity)在Java实现上与多线程是类似的,它的一些方法与生命周期都与多线程相似,这会在后面讲,而Layout布局及组价与GUI界面编程类似,组件与事件,而事件就可以理解为活动的一部分。
1:创建Activity:
开始实践。
右键包->new->Activity->Empty Activity 创建一个空活动模板。
Activity Name为活动名称,Generate Layout File勾选自动创建这个活动的Layout布局文件,Layout Name 为布局文件名称,使用默认。
创建完成后的MainActivity活动Java代码。
package com.example.yangchaojie.createactivity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
创建完成后的layout/activity_main.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.yangchaojie.createactivity.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
app/src/main/AndroidManifest.xml这个XML文件中注册,否则是无法使用的,而使用AndroidStudio进行开发的话,在Activity创建完成时,就已经帮我们自动创建了。
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
其中
<activity android:name=".MainActivity">
activity标签中制定了name .MainActivity是当前活动名称,这里是已包名在定义的,而其中的开头的.就是所有包名的缩写。
先写一个简单的Toast提醒,它可以在应用中向用户显示一些简短的消息。
比如在活动页面中增加一个按钮,让点击按钮之后显示消息。
先在res->Layout->layout/activity_main.xml增加一个按钮。
<Button
android:id="@+id/button_1"
android:text="Click Me!"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
这里指定了这个按钮的id,在接下来会用到。
这是MainActivity活动的代码。
先将Button这个按钮找到,并赋给button,而查找就类似JavaScript中的Document.getElementById。
findViewById顾名思义,是通过ID在视图中查找,返回的是找到的按钮实例。
package com.example.yangchaojie.createactivity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
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.button_1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"OK!",Toast.LENGTH_SHORT).show();
}
});
}
}
接着是绑定事件,让按钮点了之后会有反馈。
button.setOnClickListener 表示给按钮注册一个监听器,点击按钮就会执行监听器中的Onclick方法。
Toast的静态方法makeText创建一个文本Toast,由于活动本身就是一个Context对象,所以直接传入MainAvtivity.this,第二个参数便是消息的内容,第三个是显示时长,有两个可以选择,最后.show()方法展示。
运行一下。
2:在活动之间传值
新建活动:Main2Activity 。
现在有两个活动,Main1和Main2,现在想让在Main1的的数据传递到Main2。
修改主活动Main1代码如下:
package com.example.yangchaojie.createactivity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
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.button_1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Toast.makeText(MainActivity.this,"OK!",Toast.LENGTH_SHORT).show();
String name = "ZhagShan";
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
intent.putExtra("name",name);
startActivity(intent);
}
});
}
}
Intent这个对象很重要,他可以完成很多在关于活动互动的功能。
代码中,Intent对象创建了实例,Main1 和Mian2,很明显了,当前的活动已经与Mian2相关联了。
定义一个字符串,putExtra可以将数据以KV形式存储,和HashMap的put一样的,现在已经将name保持在了Intent中,启动活动。
再看Main2代码:
package com.example.yangchaojie.createactivity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
public class Main2Activity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Intent intent = getIntent();
String name = intent.getStringExtra("name");
Log.d("Main2", name);
Toast.makeText(Main2Activity.this,name,Toast.LENGTH_SHORT).show();
}
}
这个里Intent并没有像Main1那样new一个对象,因为Intent在Main1和Main2关联,而在Main2中可以直接获取在Main1中的实例。
接着通过getStringExtra("name")方法,传入键获取值。
log.d打印一下,再用Toast显示一下,活学活用。
结果:
3:返回数据给上一个活动
返回上一个活动需要按下Back键,并没有一个用于启动活动的Intent来传递数据。
在Activity中有一个startActivityForResult()方法,这个方法在活动销毁时能够返回一个结果给上一个活动。
修改Main1代码如下:
package com.example.yangchaojie.createactivity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case 1:
if(resultCode == RESULT_OK){
String returnData = data.getStringExtra("data_return");
Toast.makeText(MainActivity.this,returnData,Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button)findViewById(R.id.button_1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Toast.makeText(MainActivity.this,"OK!",Toast.LENGTH_SHORT).show();
// String name = "ZhagShan";
// Intent intent = new Intent(MainActivity.this,Main2Activity.class);
// intent.putExtra("name",name);
// startActivity(intent);
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
startActivityForResult(intent,1);
}
});
}
}
在按钮被点击时,启动Main2活动。
Main2:
package com.example.yangchaojie.createactivity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class Main2Activity extends AppCompatActivity {
@Override
public void onBackPressed() {
Intent intent =new Intent();
intent.putExtra("data_return","HelloWorld");
setResult(RESULT_OK,intent);
finish();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
// Intent intent = getIntent();
// String name = intent.getStringExtra("name");
// Log.d("Main2", name);
// Toast.makeText(Main2Activity.this,name,Toast.LENGTH_SHORT).show();
Button button = (Button)findViewById(R.id.button_2);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.putExtra("data_return","HelloWorld");
setResult(RESULT_OK,intent);
finish();
}
});
}
}
Main2中,点击按钮会将Intent放进去一个字符串,setResule是很重要的一个步骤,用来设置返回的数据,将当前的Intent传进去,接着销毁当前活动Main2。
可以看到Main1重载了onActivityResult方法,在此方法中:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case 1:
if(resultCode == RESULT_OK){
String returnData = data.getStringExtra("data_return");
Toast.makeText(MainActivity.this,returnData,Toast.LENGTH_SHORT).show();
}
}
}
有三个形参,requestCode主要用来判断数据来源,resultCode即在返回数据是传入的处理结果,Intent 结果。
switch中的requestCode就是Main1中传入的1。
接着用过resultCode的值来判断处理结果是否成功。
返回成功。
如果要在点击Back按键是也返回数据的话,在Main2中重载onBackPressed方法,重新把Intent设置一遍销毁就可以了。
@Override
public void onBackPressed() {
Intent intent =new Intent();
intent.putExtra("data_return","HelloWorld");
setResult(RESULT_OK,intent);
finish();
}
4:活动的生命周期
Android程序是通过Task来管理活动的,准确说是Stack,栈数据结构,是一种后进先出的数据结构。
每个活动生命周期最多有四种状态。
1:运行状态:
当活动压栈到栈顶时,会执行栈顶活动,这个活动此时就是运行状态。
2:暂停状态:
当活动不在栈顶时,但任然可见,处于暂停状态的活动也是系统不希望回收的。
3:停止状态
当活动不在栈顶时,并且完全不可见的时候,就会进入停止状态,系统会为这种活动保存响应的状态和成员变量,有可能被系统回收。
4:销毁状态
当活动从返回栈中移除的时候,便处于销毁状态,系统会回收这种活动,已释放手机内存。
5:活动的生存期
Activity类中定义了7个回调方法,覆盖了活动生命周期的每一个环节。
onCreate()。顾名思义,在活动创建时调用,比如加载布局,绑定事件。
onStart()。这个方法在活动由可见到不可见时吊桶。
onResume().这个方法在活动准备好与用户交互时调用,活动必须在栈顶,且处于运行状态。
onPause()。这个方法在系统准备启动和恢复另一个活动是调用,通常会在这个方式里面将消耗CPU的资源释放掉,保存关键数据。
onStop()。这个方法会在活动完全不可见时调用,和onPause()方法的主要区别在于,如果启动的新活动,是一个对话框式的活动,那么onPause()方法会得到执行,而onStop()方法不会。
onDestroy()。这个方法在活动销毁之前调用,之后活动的状态变为销毁状态。
onRestart()。这个方法在活动由停止状态变为运行状态是调用。
6:顺便说一下standard和singleTop
Standard是活动的默认启动方式,比如当前的Main1活动在返回栈中已经存在,那么再次创建Main1的时候系统还是会创建新的活动在返回栈。
Single Top启动模式,如果指定活动为Single Top启动,那么在如果栈顶已经是该活动,则可以直接使用它,不会创建新的活动实例。