目录
- 生命周期
- Activity保存当前状态
- Activity之间的跳转
- Activity 参数 回传
- 启动模式
- Activity完美退出的方法
一.Activity生命周期
一上来就是生命周期图,多少小伙伴,看到就头疼,不说了,都是泪啊。。。。
独家解析,谈谈我的理解方式
- onCreate()
在Activity被创建时回调;这个不要多说 - onStart()
在Activity画面可视之前被回调,就是你能看到之前 - onResume()
在Activity界面可互动之前被回调,你现在可以随便点击了 - onPause()
回调后Activity不再可互动; 你现在不能点击了,没办法做交互 - onStop()
回调后Activity不再可视,你就看不到了 - onDestroy()
回调后Activity被销毁
是不是以一一对应的关系,这样记得话 我感觉很容易理解, 又方便记忆
撸一撸启动时候的生命周期怎么走
一个Activity的启动顺序
onCreate()——>onStart()——>onResume()
当另一个Activity启动时
第一个Activity onPause()——>
第二个Activity onCreate()——>
onStart()——>
onResume() ——>
第一个Activity onStop()
当返回到第一个Activity时
第二个Activity onPause() ——>
第一个Activity onRestart()——>
onStart()——>
onResume() ——>
第二个Activity onStop()——>
onDestroy()
用户按下Back键返回
onPause()——>onStop()
如果新的Activity设置了透明主题,不会回调onStop() 透明主题看不到不代表没有啊
二.Activity保存当前状态
- onSaveInstance
- onRestoreInstance
这两个方法先有个印象,在应用程序设置改变(比如竖屏变横屏)、在内存不足需要腾出内存时,一个Activity可能被系统杀死(可能在之后重新启动),这时可能会造成信息的丢失,比如控件里暂时存放的数据、Activity对象里的属性值都会在Activity被系统杀死时丢失。 可以用onSaveInstance和onRestoreInstance来解决这个问题
来个例子
public class MainActivity extends Activity {
private Button button;
private TextView tv;
private int num;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button1);
tv = (TextView) findViewById(R.id.textView1);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {//按钮一被点击
num ++;//数字+1
tv.setText(Integer.toString(num));//显示到TextView
}
});
}
//在Activity可能被系统杀死时回调,用来保存杀死前的一些状态,以便以后再启动时将保存下来的状态恢复到新的Activity
//那些有id的控件的状态会默认被保存,在之后调用onRestoreInstanceState时再自动恢复
//但是Activity类中的属性的值不会被自动保存,需要我们手动保存,保存到参数Bundle outState中
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);//这句是继承下来的默认逻辑,不要删除
//将属性num的值以键值对的形式放进outState,键是一个字符串,名字随便起,但要见名知意,值就是要保存的值
outState.putInt("number", num);//放进去以后即使这个Activity被销毁,这个Bundle里面的信息会被系统保存下来
}
//横竖屏切换Activity被杀死后,会马上再创建一个Activity,会回调这个方法去恢复原来丢失的信息
//有id的控件的状态会自动恢复,但Activity属性的值需要我们在这个方法里手动恢复
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//从系统维护的Bundle对象中取出之前保存进去的值,第一个参数是键,第二个参数是没有这个键值对情况下的默认值
int n = savedInstanceState.getInt("number", 0);
// tv.setText(Integer.toString(n));//将从Bundle中取出的数字转为字符串设置到TextView中
num = n;//属性也要设置为取出来的值
}
}
ps: 这排版看着怎么就那么难受呢 = =
三.Activity之间的跳转
activity之间的跳转,一般肯定用intent
,至于不一般,在组件化中会使用路由,这玩意,还真是TM 挺麻烦的
(1)显示跳转
startActivity(new Intent(MainActivity.this,SecondActivity.class))
别忘了在manifest
添加activity
(2) 隐身跳转
在清单文件中注册action
<activity android:name=".KfcActivity">
<!-- 将这个KdfActivity的功能注册为吃,具体为com.qianfeng.EAT -->
<intent-filter>
<!-- 动作注册为com.qianfeng.EAT,一个这样的意图发给操作系统时,操作系统会找到这个符合条件的Activity并启动 -->
<action android:name="com.allens.EAT"/>
<category android:name="android.intent.category.DEFAULT"/><!-- 这个分类一定要写,不然会出错 -->
</intent-filter>
</activity>
activity中代码
Intent intent = new Intent("com.allens.EAT");// 创建一个意图,action为com.qianfeng.EAT
startActivity(intent);// 启动意图动作为com.qianfeng.EAT的一个Activity
// 启动后会将意图提交给操作系统,操作系统会在所以清单中扫描有没有一个Activity的action注册为com.qianfeng.EAT
// 如果有,就启动;如果一个也没有,就出错
如果有两个不同的Activity,拥有相同的action,系统会让用户去选择去哪个Activity
四.跳转传值
intent 传值
// 传递参数
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtra("allens", s);
startActivity(intent);
//获取参数
String str = intent.getStringExtra("allens");
Bundle
Bundle bundle = new Bundle();
//往这个Bundle对象里以键值对形式放置信息
bundle.putString("inputtext", s)
//将这一捆信息一下子放进意图对象
intent.putExtras(bundle);
当然啦,一般我们都会传一些比较复杂的对象,比如在网络获取到的数据,需要调到一个详情界面,需要把获得的数据全部调到其他界面,简单来说,就是如何传递对象
这里给出两个东东
- Parcelable
- Serializable
这两个都是接口,将对象序列化,然后传递到第二个Activity的
使用说明
//传递对象
Bundle bundle = new Bundle();
bundle.putSerializable("bundle_ser",person);//Parcelable 序列化对象
intent.putExtras(bundle);
//获取对象
Pen pen = (Pen)getIntent().getParcelableExtra("parcel_test");
intent.putExtra("tag1",data);// 序列化对象
Person per = (Person)intent.getSerializableExtra("tag1");
ps(大写的注意): 需要传递的对象都需要实现序列化接口,Android 中最好使用 Parcelable
至于二者的区别,我会在后期的文章中解释. 预知后事如何,请听下回分解
五.Activity 参数 回传
先记得这两个方法,后面解释
- startActivityForResult
- onActivityResult
有时候吧,我们需要一些参数,但是这些参数需要从第二个Activity中回传过来,哈哈,有借有还再借不能,PS 大兄弟们,救济救济我啊。。。最近穷死了 , 大写的哭
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, TwoActivity.class);
//这里采用startActivityForResult来做跳转,此处的0为一个依据,可以写其他的值,但一定要>=0
startActivityForResult(intent, 999);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//startActivityForResult 中的参数要相同
if (requestCode == 999) {
//和setResult中的参数相同
if (resultCode == 110) {
String data1 = data.getStringExtra("data");
Log.e("TAG", "data--->" + data1);
}
}
}
}
public class TwoActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent();
intent.putExtra("data", "测试的参数");
//intent为A传来的带有Bundle的intent,当然也可以自己定义新的Bundle
setResult(110, intent);
finish();//此处一定要调用finish()方法
}
}
六. 启动模式
这个问题,真心每次面试都会被问到,无奈
Activity 有4中启动模式,先说一下,然后慢慢解释
- standard
- singletop
- singleTask
- singleInstance
standard
默认的启动模式,也是标准的启动模式,打个比方,现在我们点击Button,启动当前的Activity,假设为Activity 的名字叫 A。 那么在任务栈中 就是
A A A A A A ......
稍等我一会,我去画个图 。说明一下
等待20分钟...
本着先后出的原则,任务栈中就是这样的,如果你想回退的话,只能 A3现出来,然后A2...
singletop
栈顶的两个Activity不会一样,如果栈顶有activity的实例, 则不需重新创建(只要不在栈顶就需要创建),可重用该实例,不过会调用onNewIntent()方法,如果栈顶不存在就重新创建新的实例并放入栈顶
在等我20分钟
看图,如果先启动A 然后启动 B 在启动A 那么任务栈中 是 A1 B A2 (从下往上看),如果此时 我们再次启动A 那么并不会想standard
那样 再次启动一个 A 放入栈中,栈顶只有一个A 的实例,这就是singletop
singleTask
设置了singtask的Activity如果再一次启动,它就必须在最上面,如果有其他的在ta上面就会被弹出
这个不画图了,太丑了,我看不下去
意思很简单,谁设置了, 谁是老大,在栈顶
singleInstance
这种启动模式比较特殊,因为它会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其他Activity实例进入。
扯了这么多,MD 怎么用啊!!!!!!!!
- AndroidManifest.xml配置
launchMode 属性就是对应的启动模式
<activity
android:name=".SingleInstanceActivity"
android:label="singleInstance launchMode"
android:launchMode="singleInstance"
android:taskAffinity="">
- Intent Flags设置
Intent intent = new Intent(StandardActivity.this, StandardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
七.Activity完美退出的方法
我的推荐方法是 写一个单例类,将所有的Activity 都放到一个集合中,要退出的时候,将集合中的Activity 全部finish
写在最后
以前也文章,其实就是想起来就写写,后来就不一样了,直接不写了!!!然后东西全写在有道云上,其实也还不错,但是吧,为了炫耀一下那么漂亮的老婆,哈哈哈哈哈哈。
当然,也希望,入坑的小伙伴能够一起进步。
最后,祝我新婚快乐,哈哈 刚刚结婚