标签:
人生是一场旅行,在乎的不是目的地,是沿途的风景以及看风景的心情。
本讲内容:Activity用法
一、活动被回收了怎么办?
当一个活动进入了停止状态,是有可能被系统回收的。如果一个应用有一个活动A,用户在活动A启动活动B,活动A就进入了停止状态,这个时候由于系统内存不足,将活动A回收掉,如果用户按下Back键返回活动A,这里不会执行onRestart()方法,而是执行活动A的onCreate()方法重新创建一次。但是如果活动A是可能存在临时数据和状态的,譬如:活动A中有一个文本框,现在你输入了一段文字,然后启动活动B,这时由于系统内存不足被回收,然后返回活动A,你会发现刚刚输入的文字没了,因为活动A被重建了。
如果出现这种情况会影响用户体验,Activity中提供了一个onSavedInstanceState()回调方法,这个方法会保证一定在活动被回收之前调用,因此我们可以通过这个方法来解决活动被回收时临时数据得不到保存的问题。
onSavedInstanceState()方法会携带一个Bundle类型的参数,Bundle提供了一系列的方法用于保存数据。
在Activity中添加如下代码就可以将临时数据进行保存
protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); String tempData="something you just typed"; outState.putString("data_key", tempData); }
public class MainActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(savedInstanceState!=null){ String tempData=savedInstanceState.getString("data_key"); Log.d(TAG, tempData); } } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); String tempData="something you just typed"; outState.putString("data_key", tempData); } }取出值之后再做相应的恢复操作即可,Intent传递数据也是用类似的方法,Intent还可以结合Bundle一起用于传递数据,首先可以先把需要传递的数据都保存在Bundle对象中,然后再将Bundle对象存放在Intent里。到了目标活动之后先从Intent中取出Bundle,再从Bundle中一一取出数据。
二、活动的启动模式
活动启动模式一共有四种,分别是standard、singleTop、singleTask和singleInstance,可以在AndroidManifest.xml中通过给<activity>标签指定android:launchMode属性设置启动模式。
1、standard
standard是活动默认的启动模式,我们知道Android是使用返回栈来管理活动的,在standard模式下,每当启动一个新的活动,它就会在返回栈中入栈,并牌栈顶的位置。对于使用standard模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。
示例一:
public class MainActivity extends Activity { private static final String TAG="MainActivity"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, this.toString());//打印当前实例 setContentView(R.layout.activity_main); Button button1=(Button) findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { public void onClick(View v) { //研究standard模式 Intent intent=new Intent(MainActivity.this,MainActivity.class); startActivity(intent); } }); } }运行程序,然后在MainActivity界面连续点击两次按钮,可以看到LogCat中打印信息
从打印信息中我们可以看出,每点击一次按钮就会创建一个新的MainActivity活动实例。此时返回栈中存在三个MainActivity实例,因此你需要连按三次Back键才能退出程序。
2、singleTop
在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。
示例二:(示例一基础上)
在AndroidManifest.xml文件中
<activity android:name=".MainActivity" <span style="color:#ff0000;">android:launchMode="singleTop"</span> android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>运行程序,然后在MainActivity界面连续点击按钮,可以看到LogCat中打印信息
不管你点击多少次按钮都不会再有新的打印信息出现,因为目前MainActivity已经处于返回栈的栈顶,每当想要启动一个MainActivity时都会直接使用栈顶的活动。此时返回栈中只存在一个MainActivity实例,仅按一次Back键就可以退出程序。
示例三:不过当MainActivity并未处于栈顶位置时,这里再启动MainActivity,还是会创建新的实例的。
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity { private static final String TAG="MainActivity"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, this.toString());//打印当前实例 setContentView(R.layout.activity_main); Button button1=(Button) findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent=new Intent(MainActivity.this,FirstActivity.class); startActivity(intent); } }); } }
public class FirstActivity extends Activity{ private static final String TAG="MainActivity"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, this.toString()); setContentView(R.layout.activity_first); Button button2=(Button) findViewById(R.id.button2); button2.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent=new Intent(FirstActivity.this,MainActivity.class); startActivity(intent); } }); } }运行程序,在MainActivity界面点击按钮进入FirstActivity界面,然后在FirstActivity界面点击按钮返回MainActivity界面
可以看到系统创建了二个不同的MainActivity实例,这是由于在FirstActivity启动MainActivity时,栈顶活动已经变成了
FirstActivity,因此会创建一个新的MainActivity实例。现在按下Back键会返回到FirstActivity,再按下Back键会返回到
MainActivity,再按下Back键才会退出程序。
3、singleTask
使用singleTask模式可以解决重复创建栈活动的问题,即整个返回栈中不存在重复活动实例。当活动的启动模式指定为singleTask,每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。
示例四:
在AndroidManifest.xml文件中
<activity android:name=".MainActivity" <span style="color:#ff0000;">android:launchMode="singleTask"</span> android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity { private static final String TAG="MainActivity"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, this.toString());//打印当前实例 setContentView(R.layout.activity_main); Button button1=(Button) findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { public void onClick(View v) { //研究standard模式 Intent intent=new Intent(MainActivity.this,FirstActivity.class); startActivity(intent); } }); } protected void onRestart() { super.onRestart(); Log.d(TAG, "MainActivity_onRestart()"); } }
public class FirstActivity extends Activity{ private static final String TAG="MainActivity"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, this.toString()); setContentView(R.layout.activity_first); Button button2=(Button) findViewById(R.id.button2); button2.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent=new Intent(FirstActivity.this,MainActivity.class); startActivity(intent); } }); } protected void onDestroy() { super.onDestroy(); Log.d(TAG, "FirstActivity_onDestroy()"); } }运行程序,在MainActivity界面点击按钮进入FirstActivity界面,然后在FirstActivity界面点击按钮返回MainActivity界面
可以看出在FirstActivity界面启动MainActivity界面时,会发现返回栈中已经存在一个MainActivity实例,并且在FirstActivity实例的下面,于是FirstActivity实例会从返回栈中出栈,而MainActivity实例重新成为栈顶活动,因此MainActivity的onRestart()方法和FirstActivity的onDestroy()方法会得到执行,所以现在返回栈中只剩下一个MainActivity实例了,按一下Back键就可以退出程序了。
4、singleInstance
活动会启用一个新的返回栈来管理这个活动
示例五:
将FirstActivity的启动模式设置为singleInstance
在AndroidManifest.xml文件中
<activity android:name=".FirstActivity" android:launchMode="singleInstance" > </activity>
public class MainActivity extends Activity { private static final String TAG="MainActivity"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "MainActivity_Task id id "+ getTaskId());//打印当前返回栈的id setContentView(R.layout.activity_main); Button button1=(Button) findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent=new Intent(MainActivity.this,FirstActivity.class); startActivity(intent); } }); } }
public class FirstActivity extends Activity{ private static final String TAG="MainActivity"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "FirstActivity_Task id is "+ getTaskId()); setContentView(R.layout.activity_first); Button button2=(Button) findViewById(R.id.button2); button2.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent=new Intent(FirstActivity.this,SecondActivity.class); startActivity(intent); } }); } }
下面是SecondActivity.java界面文件:
public class SecondActivity extends Activity{ private static final String TAG="MainActivity"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "SecondActivity_Task id id "+ getTaskId()); setContentView(R.layout.activity_second); } }运行程序,在MainActivity界面点击按钮进入FirstActivity界面,然后在FirstActivity点击按钮进入SecondActivity界面
可以看出FirstActivity的id不同于MainActivity和SecondActivity的id,这说明FirstActivity确实存在在一个单独的返回栈里的,而且这个返回栈中只有FirstActivity这一个活动。然后我们按下Back返回键会从SecondActivity界面返回到MainActivity界面,再按下Back键会返回到FirstActivity界面,再按下Back键才会退出程序。由于MainActivity和SecondActivity是存在在同一个返回栈里的,当当前返回栈已经空了,才显示另一个返回栈的栈顶活动。当所有返回栈空了,自然退出程序。
三、知晓当前是在哪一个活动。
如何根据程序当前的界面就能判断出这是哪一个活动。(由于项目多人参与)
示例六:
首先新建一个BaseActivity类继承自Activity,然后让BaseActivity类作为测试类的父类
public class BaseActivity extends Activity{ private static final String TAG="MainActivity"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //获取当前实例的类名 Log.d(TAG, getClass().getSimpleName()); } }然后修改MainActivity、FirstActivity和SecondActivity的继承结构,让它们不再继承自Activity,而是继承BaseActivity,虽然项目中的活动不再直接继承自Activity了,但是它们仍然完全继承Activity中的所有特性。
现在重新运行程序,依次进入MainActivity、FirstActivity和SecondActivity界面,打印
可以看出我们每当进入一个活动的界面,该活动的类名就会被打印出来。
四、随时随地退出程序。
如果当你的手机的界面还停留在SecondActivity界面,你会发现当前想要退出程序需要按三次Back键才行。按Home键只是把程序挂起,并没有退出程序。
示例七:
首先新建一个ActivityCollector类作为活动管理器
//管理所有活动 public class ActivityCollector { //通过List来暂存活动 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(); } } } }
//创建BaseActivity类作为所有类的父类 public class BaseActivity extends Activity{ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //将当前正在创建的活动添加到活动管理器里 ActivityCollector.addActivity(this); } protected void onDestroy() { super.onDestroy(); //将一个活动在活动管理器中移除 ActivityCollector.removeActivity(this); } }
public class SecondActivity extends BaseActivity{ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); Button button3=(Button) findViewById(R.id.button3); button3.setOnClickListener(new OnClickListener() { public void onClick(View v) { //不管你想在什么地方退出程序,只需要調用ActivityCollector.finishAll()即可 ActivityCollector.finishAll(); } }); } }
Take your time and enjoy it 要原码的、路过的、学习过的请留个言,顶个呗~~
标签:
原文地址:http://blog.csdn.net/liguojin1230/article/details/44998855