Activity是Android的四大组件之一,我是一个新手在刚刚开始学的时候并没有对其有更深入的了解,平时也就是会用。但是当别人问我activity的一些其他知识我还是一窍不通,所以就决定把android的四大组件再去重新的了解一下。这篇博客呢就是加深对Activity的理解。另外其他三大组件会陆续推出。
首先呢,我们来看一下如何深入的了解activity,下面是一张学习路线图
相信大家对Activity有了一定的认识,接下来就开始对这些内容,进行深入的了解
一个Activity在创建和显示的时候,先调用的是
1.onCreate, onStart, onResume,方法
2,按下back键的时候会调用:onPause,onStop,onDestory方法
3.按下home键会调用:onPause onStop
4.按下home键后再打开程序:onRestart onStart onResume
相信大家基本上有了了解了,对于这些生命周期我们现在是记住了,但是时间长了说不定我们就忘了(我就是一个笨人老是忘),我在一个视频里面看到过有位大神是这样理解这几种状态的的,我觉得还不错,就拿来用了。
一个Activity生命周期的三种状态:
1.显示状态:onCreate,onStart,OnResume
2.看不见状态:onPause,onStop
3.销毁状态:onDestory
1、进入项目->进入A界面执行 onCreate(A)->onStart(A)->onResume(A)
2、点击A中的Button进入B onPause(A)->onCreate(B)->onStart(B)->onResume(B)->onStop(A)
3、点击Back键从B进入A界面 onPause(B)->onRestart(A)->onStart(A)->onResume(A)->onStop(B)->onDestory(B)
现在我们了解了多个Activity之间的生命周期之后可能就会有大量的疑问。下面就简单的把这些疑问解答一下
1、为什么要先暂停onPause方法,再执行新的Activity的什么周期?
答:为了解答这一个问题,我们举一个例子。例如我们在听歌的时候突然之间一个电话打了进来,那么我们的理想状态是什么呢,肯定就是我们的歌先暂停,接下来我们去接电话,接完电话之后,我们的歌重新播放。onPause就是为了解决这一问题的。当我们调用这一个方法的时候。我们的歌就会先暂停下来。否则的话,我们一边接着电话,一边放着歌。用户体验恐怕相当不好吧。
2、为什么不先执行onPause、onStop方法,在执行新的Activity的生命周期
答:我们接着上面的例子。当我们接完电话的时候接下来就是回到播放歌曲的界面吧。如果我们先调用了onStop就会留下一个空档区。 什么空档区呢?就是我们电话界面回到我们的歌曲界面的时候。有可能会出现闪退(crush)的现象。
运行项目 onCreate->onStart->onResume (创建竖屏)
执行竖屏切换 onPause->onSaveInstanceState->onStop->onDestroy(销毁横屏)
onCreate->onStart->onResume (创建竖屏)
整个流程大概就是先创建一个竖屏,然后销毁竖屏,再去重新创建一个横屏 。onSaveInstanceState这个方法是干嘛的呢?就是为了保存我们的横屏信息的一些状态。那我们如何保存呢?
protected void onSavaInstanceState(Bundle outState){
Log.i(TAG,"onSavaInstanceState");
super.onSavaInstanceState(outState);
outState.putString("name","zhangsan")
}
我们首先在这个重载方法里面把我们的状态去保存。然后在我们的onCreate方法里面去拿
if(savaInstanceState!=null){
textView.setText(savadInstanceState.getString("name"));
}
但是需要说明的是 ,我们一般在开发的时候不去切换。这样会增大我们的开发难度。也没什么必要对吧。
1、隐式调用activity 在mainifest中配置被调用的activity的设置
2、在类中的onclick方法中
Intent intent=new Intent();
intent.setClass(A.this,B.class);表示从A->B
startActivity(intent);
1、启动系统浏览器 Intent intent=new Intent(); intent.setAction(Intent.ACTION_VIEW) Uri url=Uri.parse("http://www.baidu.com"); intent.setData(url); startActivity(intent); 2、启动系统图库 Intent intent=new Intent(); intent.setAction(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); startActivity(intent); 3、启动系统短信 Intent intent=new Intent(); intent.setAction(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT,"hello world"); startActivity(intent); 4、启动拨号器 Intent intent=new Intent(); intent.setAction(Intent.ACTION_VIEW) Uri url=Uri.parse("tel:13766257357"); intent.setData(url); startActivity(intent);
传递Bitmap对象、
Intent intent = new Intent( );
Bundle bundle = new Bundle();
Bitmap bitmap = BitampFactory.decodeResource(getResoruces(),R.drawable.ic_launch);
bundler.putParcelable("bitmap",btimap);
intent.putExtras(bundle);
startActivity(intent);
接收数据
Intent intent=getIntent();
if(intent!=null){
Bitmap bitmap=intent.getParcelableExtra("bitmap");
imageView.setImageBitmap(bitmap);
}
bundle传递数据大于0.5M会抛出传输数据过大异常;在传输大量数据的时候也有可能抛出TransactionTooLargeException异常,解决办法是减少bundle传输的数据量
但是如果我们碰到要传输大量数据的时候该用什么方法呢?那就太多了。我们可以使用File,SqLite数据库等等。IPC通讯机制也可以。传递大量数据会有点麻烦。
Task和BackStack概念,我们这里给出官方的介绍
file:///D:/software/Eclipse/adtbundlewindowsx8620140702/adtbundlewindowsx8620140702/sdk/android_sdk_docs_offline_20/docs/guide/components/tasks-and-back-stack.html
1. 启动一个app,framework都会为这个app分配一个Task,有对应的TaskID和stack,然后在这个APP中所有的activity都共用一个TaskID和stack。
2. 当从一个app的进程跳转到另一个app进程时,还是在同一个task中,这就是Task允许跨进程间调用。通过在manifest中声明activity "android:process=XXX"可以指定这个activity为另一个进程
3. Back Stack
一个Task就是一系列的activity的集合,这些activity以打开的顺序放入一个stack中,最后打开的activity最先出来。对于一个app来说,main activity就在栈顶的位置。在一个app中可能会调用其他app的activity,但即使两个activity不在同一个APP中,但是其TaskID是同一个,属于同一个Task Stack
4. android中的多任务
假设启动了APP1,对应创建了一个Task A,它有三个activity。然后回到home screen,启动APP2,对应创建了一个Task B。此时,Task A的activity虽然全部stop了,但是Task A的stack还是完整存在的。然后可以通过回到home screen或点击recent apps启动Task A,它的activity回到前台。
5. dumpsys activity
(1)running activities部分可以查看当前正在运行的activity
(2)mFocusedActivity可以查看正在获取焦点的activity
(3)Recent tasks可以查看最近的一些任务
接下来我们给出一个例子看一下,到底是如何运行的(在一个Activity中打开一个新的Activity)
重要提示:在Manifest文件中给要新打开的Activity配置一个Android:process属性,指定该属性后这个Activity就属于另外一个进程的Activity,就会在另外一个进程中创建该Activity。可以在上面两个Activity的onCreate方法中用Log日志打印一下当前Activity的task id使用getTaskid()方法。两个提示示例代码如下:
<activity android:name=".NewActivity" android:process=":NewActivity"/>
// 在MainActivity的onCreate方法中添加
Log.i("Tag", "MainActivity taskId"+getTaskId());
// 在NewActivity的onCreate方法中添加
Log.i("Tag", "NewActivity taskId"+getTaskId());
写完后运行Demo,在MainActivity中点击按钮打开新的NewActivity。切换到eclipse的DBMS界面可以查看到这两个Activity的进程id是不同的
在查看后台打印的Log他们的testId都是相同的所以他们是在同一个任务栈中
public class ActivityCollector {
//声明一个List集
public static List activities=new ArrayList();
//将activity添加到List集中
public static void addActivity(Activity activity){
activities.add(activity);
}
//将某一个Activity移除
public static void removeActivity(Activity activity){
activities.remove(activity);
}
//结束所有添加进来的的Activity
public static void finishAll(){
for(Activity activity:activities){
//如果activity没有销毁,那么销毁
if(!activity.isFinishing()){
activity.finish();
}
}
}
}
作用一看就明白了吧。我们再定义一个BaseActivity。让A,B,C,D全都继承它。
public class BaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//将得到的Activity的名字在后台打印
Log.i("info", getClass().getSimpleName());
//将启动的Activity添加进来
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
ActivityCollector.removeActivity(this);
super.onDestroy();
}
}
这个类的作用就是,在A,B,C。D启动的时候将其实例添加到List集合中。退出的时候删除实例。
public class A extends BaseActivity {
private Button bt1;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_a);
super.onCreate(savedInstanceState);
bt1=(Button) findViewById(R.id.button1);
bt1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(A.this,B.class);
startActivity(intent);
}
});
}
}
下面是D的只有一行不同。也特别简单
public class D extends BaseActivity {
private Button bt1;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_d);
super.onCreate(savedInstanceState);
bt1=(Button) findViewById(R.id.button4);
bt1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//结束所有的Activity退出程序.
ActivityCollector.finishAll();
}
});
}
}
这就是所有的代码了。当我们点击D中的按钮之后,就能退出所有的Activity了。