该目录为Android的一些学习笔记。
Android四大组件之—-Activity
Android中有4大组件,它们分别是Activity、Service、BroadcastReceiver、ContentProvide。它们的功能如下表:
要学Activity首先肯定要了解Activity的生命周期,首先我们看Android官方API的介绍:
先来了解下,Activity中重要的四种状态和七种方法
一)四种状态
1. 活动(Active/Running)状态
当Activity运行在屏幕前台(处于当前任务活动栈的最上面),此时它获取了焦点能响应用户的操作,属于运行状态,同一个时刻只会有一个Activity 处于活动(Active)或运行
暂停(Paused)状态
当Activity失去焦点但仍对用户可见(如在它之上有另一个透明的Activity或Toast、AlertDialog等弹出窗口时)它处于暂停状态。暂停的Activity仍然是存活状态(它保留着所有的状态和成员信息并保持和窗口管理器的连接),但是当系统内存极小时可以被系统杀掉
停止(Stopped)状态
完全被另一个Activity遮挡时处于停止状态,它仍然保留着所有的状态和成员信息。只是对用户不可见,当其他地方需要内存时它往往被系统杀掉
Activity 尚未被启动、已经被手动终止,或已经被系统回收时处于非活动的状态,要手动终止Activity,可以在程序中调用”finish”方法
二)七种方法
通常用于初始化设置: 1、为Activity设置所要使用的布局文件2、为按钮绑定监听器等静态的设置操作
onCreate(Bundle savedInstanceState);
当Activity可见未获得用户焦点不能交互时系统会调用
onStart();
当Activity已经停止然后重新被启动时系统会调用
onRestart();
当Activity可见且获得用户焦点能交互时系统会调用
onResume();
当系统启动另外一个新的Activity时,在新Activity启动之前被系统调用保存现有的Activity中的持久数据、停止动画等,这个实现方法必须非常快。当系统而不是用户自己出于回收内存时,关闭了activity 之后。用户会期望当他再次回到这个activity 的时候,它仍保持着上次离开时的样子。此时用到了onSaveInstanceState(),方法onSaveInstanceState()用来保存Activity被杀之前的状态,在onPause()之前被触发,当系统为了节省内存销毁了Activity(用户本不想销毁)时就需要重写这个方法了,当此Activity再次被实例化时会通过onCreate(Bundle savedInstanceState)将已经保存的临时状态数据传入因为onSaveInstanceState()方法不总是被调用,触发条件为(按下HOME键,按下电源按键关闭屏幕,横竖屏切换情况下),你应该仅重写onSaveInstanceState()来记录activity的临时状态,而不是持久的数据。应该使用onPause()来存储持久数据。
onPause();
当Activity被新的Activity完全覆盖不可见时被系统调用
onStop();
当Activity(用户调用finish()或系统由于内存不足)被系统销毁杀掉时系统调用,(整个生命周期只调用1次)用来释放onCreate ()方法中创建的资源,如结束线程等
onDestroy();
我自己本来也想个写了实例测试,发现网上早有大神测试过了,故我这里就不自己来了,直接将两分钟彻底让你明白Android Activity生命周期(图文)!
应用过来,这里基本讲全了,我这里补充点屏幕切换时的生命周期以及Activity切换时的状态变化。
在横竖屏切换时,网上有人是这么说的
1、运行Activity,得到如下信息
onCreate–>
onStart–>
onResume–>
2、按crtl+f12切换成横屏时
onSaveInstanceState–>
onPause–>
onStop–>
onDestroy–>
onCreate–>
onStart–>
onRestoreInstanceState–>
onResume–>
3、再按crtl+f12切换成竖屏时,发现打印了两次相同的log
onSaveInstanceState–>
onPause–>
onStop–>
onDestroy–>
onCreate–>
onStart–>
onRestoreInstanceState–>
onResume–>
onSaveInstanceState–>
onPause–>
onStop–>
onDestroy–>
onCreate–>
onStart–>
onRestoreInstanceState–>
onResume–>
4、修改AndroidManifest.xml,把该Activity添加android:configChanges=”orientation”,执行步骤3
onSaveInstanceState–>
onPause–>
onStop–>
onDestroy–>
onCreate–>
onStart–>
onRestoreInstanceState–>
onResume–>
5、再执行步骤4,发现不会再打印相同信息,但多打印了一行onConfigChanged
onSaveInstanceState–>
onPause–>
onStop–>
onDestroy–>
onCreate–>
onStart–>
onRestoreInstanceState–>
onResume–>
onConfigurationChanged–>
6、把步骤5的android:configChanges=”orientation” 改成 android:configChanges=”orientation|keyboardHidden”,执行步骤3,就只打印onConfigChanged
onConfigurationChanged–>
7、执行步骤4
onConfigurationChanged–>
onConfigurationChanged–>
总结:
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
但是我用Genymotion测试后发现得到的结果和他有些差距。首先启动Activty同样是
我切换成横屏也和他一样
但是我切换回竖屏是却不是他说的会打印2次
之间的原因我怀疑是模拟器的问题。
在Activity切换时,状态变化则是
启动第一个界面Activity One时,它的次序是
onCreate (ONE) - onStart (ONE) - onResume(ONE)
打开第二个Activity:
onPause(ONE) - onCreate(TWO) - onStart(TWO) - onResume(TWO)
Back后第一个Activity:
onPause(TWO) - onActivityResult(ONE) - onResume(ONE) - onStop(TWO) - onDestroy(TWO)
最后是按下HOME键:
Activity中数据传递的方法
1、使用剪切板方式clipboardManager
Activity A 中的内容传值到Activity B
A中代码:
String name = "XXXXXXXX";
ClipboardManager cm = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
cm.setText();
Intent in = new Intent(MainActivity.this, Other.class);
startActivity(in);
B中代码:
ClipboardManager cm = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
cm.getText();
2、使用intent传值
方法一:只需传递少量参数
Activity A 中的内容传值到Activity B
A中代码:
Intent intent = new Intent();
intent.setClass(getApplicationContext(), SecondActivity.class);
intent.putExtra("username","Cui");
startActivity(intent);
B中代码:
Intent intent2 = getIntent();
String str = intent2.getStringExtra("username");
textview2.append(str);
方法二:通过Bundle封装数据进行传递
Activity A 中的内容传值到Activity B
A中代码:
Intent intent=new Intent();
intent.setClass(OneActivity.this, OtherActivity.class);
Bundle bundle = new Bundle();
bundle.putString("user", "Cui");
bundle.putInt("number", 12312);
intent.putExtras(bundle);
startActivity(intent)
B中代码:
Bundle bundle = new Bundle();
bundle = intent2.getExtras();
String str4 = bundle.getString("user");
int num = bundle.getInt("number");
textview4.append(str4 + num);
3、使用Application
在Android中,有一个名为Application的类,我们可以在Activity中使用getApplication(),方法来获得,它是代表我们的应用程序的类,使用它可以获得当前应用的主题,资源文件中的内容等,这个类更灵活的一个特性就是可以被我们继承,来添加我们自己的全局属性。
使用方法为继承Application,定义所需类型变量,定义对应的get 和 put 方法即可
/**************************************************/
之前我们都是使用startActivity(intent)进行Activity之间的切换,还有一种常用的Activity切换的方法是startActivityForResult(intent, requestCode)
startActivityForResult:
startActivityForResult的主要作用就是它可以回传数据,可以一次性完成这项任务,当程序执行到这段代码的时候,假若从T1Activity跳转到下一个TActivity,而当这个T2Activity调用了finish()方法以后,程序会自动跳转回T1Activity,并调用前一个T1Activity中的onActivityResult( )方法。
这里需要注意的还有两个方法—–onActivityResult(int requestCode, int resultCode, Intent data),setResult(int resultCode, Intent data)。下面将直接在例子中说明各个函数的使用。
Activity First:
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
@SuppressLint("NewApi")
public class MainActivity extends Activity {
TextView tv1;
Button btn1,ed_btn1,ed_btn2;
EditText ed_text1,ed_text2;
Intent intent;
private int requestCode;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("MainActivity", "onCreate ~~~~");
btn1 = (Button) findViewById(R.id.btn1);
intent = new Intent();
intent.setClass(getApplicationContext(), SecondActivity.class);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
intent.putExtra("username","Cui");
intent.putExtra("password", "Did you love me");
ClipboardManager cm = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
cm.setText("ClipboardManager传递的参数");
Bundle bundle = new Bundle();
bundle.putString("user", "Cui");
bundle.putInt("number", 12312);
intent.putExtras(bundle);
startActivity(intent);
}
});
ed_text1 = (EditText) findViewById(R.id.ed_text1);
ed_text2 = (EditText) findViewById(R.id.ed_text2);
ed_text1.setText("EditText 01 ");
ed_text2.setText("EditText 02 ");
ed_btn1 = (Button) findViewById(R.id.ed_btn1);
ed_btn2 = (Button) findViewById(R.id.ed_btn2);
ed_btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
requestCode = 1;
startActivityForResult(intent, requestCode);
}
});
ed_btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
requestCode = 2;
startActivityForResult(intent, requestCode);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
String text1 = data.getStringExtra("ed_text1");
String text2 = data.getStringExtra("ed_text2");
switch (resultCode) {
case RESULT_OK:
if(requestCode == 1){
ed_text1.setText(text1);
}
else{
ed_text2.setText(text2);
}
break;
default:
break;
}
}
}
Activity Second:
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class SecondActivity extends Activity {
TextView textview2,textview3,textview4;
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
textview2 = (TextView) findViewById(R.id.textview2);
textview3 = (TextView) findViewById(R.id.textview3);
textview4 = (TextView) findViewById(R.id.textview4);
Intent intent2 = getIntent();
String str = intent2.getStringExtra("username");
String str2 = intent2.getStringExtra("password");
textview2.append(str + str2);
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
String str3 = (String) cm.getText();
textview3.append(str3);
Bundle bundle = new Bundle();
bundle = intent2.getExtras();
String str4 = bundle.getString("user");
int num = bundle.getInt("number");
textview4.append(str4 + num);
Intent intent3 = new Intent();
intent3.putExtra("ed_text1", "我改变了EditText1的值");
intent3.putExtra("ed_text2", "我改变了EditText2的值");
setResult(RESULT_OK, intent3);
}
}
运行程序后,点击”go to next Activity”
将在SecondActivity中显示各种传递Activity传递数据的方法结果。
BACK键返回,MainActivity后点击EditText下面的两个Button
进入SecondActivity后在BACK键返回MainActivity,得到
至此,关于Activity的知识学习到此。