安卓的活动会覆盖,实现的机制用的是栈
四种:
运行状态;
暂停状态;
停止状态;
销毁状态;
七个
onCreate();
onStart();
onResume();
onPause();
onStop();
onDestroy();
onRestart();
三个Activity,一个NormalActivity, 一个DialogAcitvity, 一个MainActivity
NormalActivity:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.normal_layout);
}
DialogAcitvity:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.dialog_layout);
}
配置:
<activity android:name=".MainActivity" android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".NormalActivity">
</activity>
<activity android:name=".DialogActivity" android:theme="@android:style/Theme.Dialog" >
</activity>
MainActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
Button startNormalActivity = (Button) findViewById(R.id.start_normal_activity);
Button startDialogActivity = (Button) findViewById(R.id.start_dialog_activity);
startNormalActivity.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this, NormalActivity.class);
startActivity(intent);
}
});
startDialogActivity.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this, DialogActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Log.d(TAG, "onStart");
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Log.d(TAG, "onResume");
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Log.d(TAG, "onPause");
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.d(TAG, "onStop");
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d(TAG, "Destory");
}
@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
Log.d(TAG, "Restart");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
依次进入每个活动,MainActivity的状态:
onCeate()->onStart->onResume->
进入Normal:
onPause->onStop
返回:
onRestart->onStart->onResume
点击DialogAcitivity
onPause(没有onStop,因为这是对话框形式,所以MainActivity没有stop)
返回:
onResume
最后再返回:
onPause->onStop->onDestory
如果内存不足,先开的活动被回收了,在返回那个活动时,会重新onCreate,同时活动的数据也没了。因此需要新的机制:onSaveInstanceState来解决保存回收前的已有数据问题。
@Override
//这里面的Bundle就是onCreate的Bundle参数
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
String tempDate = "要保存的内容";
outState.putString("data_key", tempDate);
}
onCreate里面取数据:
if(savedInstanceState!=null){
String tempData = savedInstanceState.getString("data_key");
Log.d(TAG, tempData);
}
Tip:Intent可以和Bundle一起用于传递数据,首先可以将Bundle放在Intent里面,然后传递Intent
standard 是活动默认的启动模式,在不进行显式指定的情况下,所有活动都会自动使用这种启动模式。因此,到目前为止我们写过的所有活动都是使用的 standard 式。在 standard 模式(即默认情况)下,每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置。对于使用standard 模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例
FirstActivity里的onClick:
Intent intent = new Intent(FirstActivity.this, FirstActivity.class);
startActivity(intent);
onCreate里面:
加上:
Log.d("FirstAcitivity",this.toString());
点击按钮也就是自己调用自己,结果:需要自己按多次返回键
配置文件中的Activity加上android:launchMode=”singleTop”属性,表示只有一个实例
但是如果活动不是在栈顶,还是会创建多个实例:
FirstActivity和SecondActivity互相循环调用,就不算是singleTop模式,仍然需要按多次返回
在整个应用程序的上下文中只有一个实例,就不能循环调用(创建)了,2调用1,因为1已经在栈,所以2直接出栈调用1,2会被销毁。不像上面直接创建一个新的1。SingleTop会往上累加Activity,而singlTask,往下找Activity,找到后进入该Activity并会退出当前活动
指定为 singleInstance 模式的活动会启用一个新的返回栈来管理这个活动(其实如果 singleTask 模式指定了不同的 taskAffinity,也会启动一个新的返回栈) 。那么这样做有什么意义呢?想象以下场景,假设我们的程序中有一个活动是允许其他程序调用的,如果我们想实现其他程序和我们的程序可以共享这个活动的实例,应该如何实现呢?使用前面三种启动模式肯定是做不到的,因为每个应用程序都会有自己的返回栈,同一个活动在不同的返回栈中入栈时必然是创建了新的实例。而使用singleInstance 模式就可以解决这个问题,在这种模式下会有一个单独的返回栈来管理这个活动,不管是哪个应用程序来访问这个活动,都共用的同一个返回栈,也就解决了共享活动实例的问题。
案例:
1调用2,2调用3,2设置为singleInstance。
结果是1,3的taskid是相同的,与2不同,说明2放在了另一个栈中,返回时直接从3返回到1,再返回到2,再退出(因为1,3在同一个栈,所以2单独放在最后才退出)。
加上这句(可以知道哪个Activity继承了这个Activity,如果继承了,都会打出BaseActivity,因为这句话加载BaseActivity中的onCreate中)
Log.d("BaseActivity", getClass().getSimpleName());
每次完全退出,都要按返回,知道主活动,如何才能快速的退出
设计一个Collector类,一旦有活动(继承同一个活动)创建,在加入list(基类Activity中的onCreate方法中加入),finishAll()方法可以直接退出(最后一层调用button的onclick里面调用),这样不用一次一次返回了
public static List<Activity> activities = new ArrayList<Activity>();
public static void addActivity(Activity activity){
activities.add(activity);
}
public static void removeActivity(Activity activity){
activities.remove(activity);
}
public static void finishAll(){
for(Activity activity:activities){
if(!activity.isFinishing()){
activity.finish();
}
}
}
假设 SecondActivity 中需要用到两个非常重要的字符串参数,在启动 SecondActivity 的时候必须要传递过来,那么我们很容易会写出如下代码:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("param1", "data1");
intent.putExtra("param2", "data2");
startActivity(intent);
这样写是完全正确的,不管是从语法上还是规范上,只是在真正的项目开发中经常会有对接的问题出现。比如 SecondActivity 并不是由你开发的,但现在你负责的部分需要有启动SecondActivity 这个功能,而你却不清楚启动这个活动需要传递哪些数据。这时无非就有两种办法,一个是你自己去阅读 SecondActivity 中的代码,二是询问负责编写 SecondActivity的同事。你会不会觉得很麻烦呢?其实只需要换一种写法,就可以轻松解决掉上面的窘境.
我们在 SecondActivity 中添加了一个 actionStart()方法,在这个方法中完成了 Intent 的构建,另外所有 SecondActivity 中需要的数据都是通过 actionStart()方法的参数传递过来的,然后把它们存储到 Intent 中,最后调用 startActivity()方法启动 SecondActivity(原因在于函数一般都会注明参数,可以自己看)
public static void actionStart(Context context, String data1, String data2){
Intent intent = new Intent(context, SecondActivity.class);
intent.putExtra("param1", data1);
intent.putExtra("param2", data2);
context.startActivity(intent);
}
在FirstActivity里面的onClick中加入:
SecondActivity.actionStart(FirstActivity.this, "data1", "data2");