android四大组件之activity(一)

            --简介

            --一.actiivty的生命周期

            --二.activity的启动模式

            --三.activity的启动方式

            --四.activity的数据传递以及数据回传

            --五.activity的横竖屏之间的转化

            --六.一些特定方法的特定讲解

            --七.activity保存数据和状态。

            --八.activity在清单文件中的配置详解以及例子:

   简介:

            activitiy是android四大组件之一,是我们在平常的运用到最多的组件

一activity的生命周期

          1.1总的来说activity的生命周期就是六个状态,7个方法。如图:


1.2上述activity的六个状态以及相关情况如下:

activity状态 执行完之后方法之后所处的状态 对用户是否可见 是否可以与用户交互 activity在该状态下停留时间长短
 Created OnCreate()方法执行完毕之后 不可见 不可交互 短暂
Started OnStart()方法执行完毕之后 可见 不可交互 短暂
Resumed(running OnResume()方法执行完毕之后 可见 可交互 较长
Paused OnPause ( ) 方法执行完毕之后 可见 不可交互 较长
Stoped OnStop ( )  方法执行完毕之后 不可见 不可交互 较长
Destroyed OnDestroy ( ) 方法执行完毕之后 不可见 不可交互 短暂

 注意:其中Paused这个状态有两种情况:

第一种:有一个半透明的activity完全覆盖在本activity上边。

第二种:有一个activity覆盖在本activity上边,但是没有完全覆盖。


1.3各种情况下生命周期走的方法:

                    情况1:从acitivityA跳到activityB,首先activityA执行的是oncreate()--onstart()--onresume(),当从activityA跳转到activityB的时候,此时执行的方法activityA的onPause()--activityB的oncreate()----activity B的onstart()---activityB 的onresume()--activity A的onstop()方法,然后点击返回键,从activityB返回到activityA,此时执行的方法是activityB的onpause()--activityA的onrestsrt()--activityA的onstart()--activityA的onresume()--activityB的onstop()---activityB的ondestroy()方法。

                    情况2:当这个activity启动之后,退居后台,已经执行了onstop方法,但是此时系统内存不够的时候,杀死了该process,那么下次要执行的就是oncreate--onstart()--onresume(),而不是执行onrestart()--onstart()--onresume()方法。

       

二.activity的启动模式

                2.0 Application, Task ,Process之间的区别

                              Application,在android中,总体来说就是一组组件的集合,众所周知,android是在因公层组件化程度非常高的系统,android开发其实就是写android四大组件中的我们需要的组件,并且在清淡文件中注册这些组件之后,把这些组件和组件使用到的资源打包称apk,然后这就是一个Application,其实Application和组件的关系可以在manifest文件中清晰体现出来,在apk安装的时候,系统会读取application中清淡文件manifest的信息,将所有的额组件解析出来,一边在运行时进行实例化。

                               Task是在程序运行的时候,只针对activity的概念,即Task是一组相互关联的正在运行的activity的集合。它是存在与framework层的一个概念,控制界面的跳转和返回,framework是以栈的数据结构方式管理用户开启的activty,也可以说activity是存在于back stack(回退栈)中的。而且task是可以跨应用的,即不同的app的activity是可以在同一个Task中的,主要是为了保证用户操作的连贯性。(比如在app中的activityA页面打开一个网页(使用第三方浏览器),当用户浏览完网页的信息之后,按back键,就会回到activityA页面。

                                Process即进程是操作系统进行资源分配和调度的一个独立单位,默认情况夏,一个应用程序的所有组件会在同一个进程中,但是应用的不同组件也是可以运行在不同的进程中的,只需要在清单文件中进行注册的时候,声明process属性:

      
      
      
      
  1. <activity android:name=".health.healthListActivity"
  2. android:process="processb">
  3. activity>

                2.1acitivty的四种启动模式

                    <1>standard--默认的启动模式,同一个任务中可以存在多个该activity的实例。不断的利用startActivity()或者 startActivityForResult()启动该activty,都会重新创建该activity的新实例。

                    <2>singleTop--(作用:防止activity被重复启动多个)--同一任务栈中可以存在多个该activity的实例,但是当该actiivty已经处在任务栈的栈顶时,此时再利用startActivity()或者startActivityForResult()启动该activity,则会复用栈中已经存在的该activity实例;如果该activity任务栈的栈顶时,此时就会重新创建新的该activity实例。

                    <3>singleTask--(作用:保证任务栈中只有一个该activity实例)--同一任务栈中只能存在一个该activity的实例,当该activity不在任务栈的栈顶的时候,此时利用startActivity()或者startActivityForResult()启动该activity,则直接杀死该activity上边的所有activity实例,让该activiyt处在任务栈的顶端;如果该activity在任务栈的顶端的时候,此时再利用startActivity()或者startActivityForResult()启动该actiivty,则直接走onNewIntent()--onRestart()--onStart()--onResume()方法。

                    <4>singInstance--(作用:保证整个系统内存中都只有一个该activity实例)--在一个新的任务栈中创建该activity的实例,并且让多个应用共享栈中的该activiyt实例,一旦存在,如果再次 利用startActivity()或者startActivityForResult()启动该actiivty,均是复用已经存在的该activity实例。               


三.activity的显示启动和隐士启动

         1activity的显式启动

                    1.1有两种方式:

                    第一种方式:setClass(上下文,类名.class);

                    第二种方式:setClassName(应用报名,类名的全路径名(应用报名+类名));

                     1.2例子: 

      
      
      
      
  1. //这是第一种
  2. Intent intent = new Intent(this,ThirdActivity.class);
  3. // intent.setClass(this, ThirdActivity.class);
  4. startActivity(intent);
  5. //这是第二种
  6. Intent intent = new Intent();
  7. intent.setClassName("com.qindong.activityappliction","ThirdActivity");
  8. startActivity(intent);

             2activity 的隐士启动:

                    2.1隐士启动的运行过程:

                            当使用隐士意图启动activity的时候,此时系统会遍历所有应用的清单文件,寻找是否存在与隐士intent匹配的intent—filter,如果找到,那么就会把intent-filter对应的activity启动起来,如果找不到,就会抛出异常ActivityNotFoundException。

                    2.2隐士启动的格式:

     
     
     
     
  1. <activity android:name=".SecondActivity">
  2. <intent-filter>
  3. <action android:name="a.b.c"/>
  4. <data android:scheme="xuexi" android:mimeType="text/name"/>
  5. <category android:name="android.intent.category.DEFAULT"/>
  6. intent-filter>
  7. activity>      

      
      
      
      
  1. intentfilter中属性:
  2. action--动作(可以自定义,可以使用系统自带的)
  3. data --数据(操作的内容)
  4. scheme--数据的标签
  5. mimeType--描述数据的类型
  6. category--类别(默认类别,机顶盒,车载模式)

            

                此时在启动这个activity的时候,就要调用setAction(),setData()方法,进行匹配。如果隐士意图的activity配置的categoty属性配置的如图所示(即默认),那么我们就不用使用addCategory()方法--系统会默认添加,如果隐士意图的activity 配置的categoty属性配置的不是如果所以,那么此时在启动activity的时候,就要手动的使用addCategory()方法进行匹配。  

                       2.3注意:

                            <1>首先配置信息中的意图过滤器中的data数据是setdata(Uri.parse("标签:"))的标签,利用setData方法可以传递,在跳转后的actiivty通过getIntent().getData()获取intent中的数据。

                           <2>如果一个activity想要被隐士启动,就必须在清淡文件中给这个activity配置intent—filter,一个activity可以有多个intent-filter。

                           <3>在给一个activity配置intent-filter的时候,intent-filter有三个属性,《action》《date》《category》,一个intent-filter可以有多个action,多个data,但是只能配置一个category。

                           <4>当一个actiivty有多个intent-filter的时候,此时只需要匹配一个即可。

                           <5>当一个activity的intent-filter由多个action,多个data的时候,此时只需要匹配一个action和一个data即可,如果只匹配action或者data这两个其中一个,是不能启动这个activity 的

                            <6>intent-filter的属性data,有很多属性,其中mimetype(描述数据的类型)是其中之一,当一个date同时schme和mimetype两个属性的时候,此时在启动这个activity的时候,要调用setDateAndType(String data,String type),而不是用setData()和setType()方法,因为这两个方法互斥。

                        2.4隐士启动的常见例子:

                                    <1>启动拨号器

      
      
      
      
  1. Intent intent=new Intent();
  2. intent.setAction(Intent.ACTION_DIAL);
  3. startActivity(intent);

                                    <2>打电话

      
      
      
      
  1. Intent intent=new Intent();
  2. intent.setAction(Intent.ACTION_CALL);
  3. intent.setData(Uri.parse("tel:15138157556"));
  4. startActivity(intent);

                                    <3>利用浏览器打开一个网页url

      
      
      
      
  1. Intent intent=new Intent();
  2. intent.setAction(Intent.ACTION_VIEW);
  3. intent.setData(Uri.parse("http://www.baidu.com"));
  4. startActivity(intent);
                                    <4>当我们要使用定制版的浏览器来打开网页的话,就要使用显示启动:
                                     intent.setClassName("应用报名","应用报名+类名");
                                    这种方式我们一般不常用,原因如下:
                                                《1》因为如果指定浏览器的话,其应用的包名以及类名有可能一次代码重构就都发生了改变,这样的话,我们就得手动进行改正了。
                                                《2》如果指定浏览器,就会降低用户的选择性,从而使用户对应用的整体印象不佳。

                      2.5activity两种启动方式的使用场景

                                    启动同一应用的activity,使用显式启动方式,显式的效率高于隐士。

                 启动不同应用的activity,使用隐士启动方式。



四。activity间数据传递

            在actiivty之间进行数据传递,不管是正向传递还是回传,都是通过intent来进行传递数据的。

       1.intent可以传递的数据类型:

                *八种基本数据类型以及数组

                *字符串以及数组

                *实现了序列化接口(Serializable----Parcelable)的类的对象以及实现了Parcelable接口的对象数组。

                *Bundle对象 

                *四种类型的ArrayList()<> ,四种类型分别是String,Integer,charsequence,继承parcelable的对象。          

        2.intent数据传递的具体方式例子:

                                 

      
      
      
      
  1. Intent intent=new Intent(this,SecondActivity.class);
  2. //第一种类型:这是通过四种ArrayList类型来传递数据
  3. intent.putCharSequenceArrayListExtra("charSequenceArraylist",charsequenceArrayList);
  4. intent.putStringArrayListExtra("stringArraylist",stringArrayList);
  5. intent.putIntegerArrayListExtra("IntegerArrayList",integerArrayList);
  6. // intent.putParcelableArrayListExtra("parcelableArrayList",);
  7. startActivity(intent);
  1. Intent intent = getIntent();
  2. //这是获取四种arryalist其中的三种
  3. if (null != intent && null != intent.getCharSequenceArrayListExtra("charSequenceArraylist")) {
  4. ArrayList<CharSequence> charSequenceArraylist = intent.getCharSequenceArrayListExtra("charSequenceArraylist");
  5. tv_second_charSequenceArraylist.setText(getString(R.string.secondActivity_charSequenceArrayList, getArrayListData(charSequenceArraylist)));
  6. }
  7. if (null != intent && null != intent.getStringArrayListExtra("stringArraylist")) {
  8. ArrayList<String> stringArraylist = intent.getStringArrayListExtra("stringArraylist");
  9. tv_second_stringArraylist.setText(getString(R.string.secondActivity_stringArraylist, getArrayListData(stringArraylist)));
  10. }
  11. if (null != intent && null != intent.getIntegerArrayListExtra("IntegerArrayList")) {
  12. ArrayList<Integer> integerArrayListExtra = intent.getIntegerArrayListExtra("IntegerArrayList");
  13. tv_second_integerArrayList.setText(getString(R.string.secondActivity_IntegerArrayList, getArrayListData(integerArrayListExtra)));
  14. }

       
       
       
       
  1.            
               
               
               
    1. Intent intent=new Intent(this,SecondActivity.class);
    2. //第二种类型:这是通过八种基本数据类型及其数组传递数据
    3. intent.putExtra("boolean",false);
    4. intent.putExtra("byte",1);
    5. intent.putExtra("int",12);
    6. intent.putExtra("short",44);
    7. intent.putExtra("long",55);
    8. intent.putExtra("float",33.0);
    9. intent.putExtra("double",22.22);
    10. intent.putExtra("char",'a');
    11. startActivity(intent);
    12. //这是取数据
    13. Intent intent = getIntent();
    14. if (null != intent) {
    15. String data= intent.getBooleanExtra("boolean", true) + "";
    16. tv_second_base_data_style.setText(getString(R.string.secondActivity_ase_data_style,data));
    17. }


       
       
       
       
  1. Intent intent=new Intent(this,SecondActivity.class);
  2. //第四种类型:这是通过继承了serialable或者paralable的对象以及继承的parable对象的数组来进行传递数据
  3. intent.putExtra("serialable",xiaoming);
  4. intent.putExtra("paralable",teacher);
  5. startActivity(intent);
  6. //取数据
  7. Intent intent = getIntent();
  8. if (null != intent && null != intent.getSerializableExtra("serialable")) {
  9. Student student = (Student) intent.getSerializableExtra("serialable");
  10. tv_second_serializable.setText(getString(R.string.secondActivity_serializable, student.getName() + student.getAge() + student.getGrade()));
  11. }
  12. if (null != intent && null != intent.getParcelableExtra("paralable")) {
  13. Teacher teacher = intent.getParcelableExtra("paralable");
  14. tv_second_parcelable.setText(getString(R.string.secondActivity_parcelzable, teacher.getName() + teacher.getAge()));
  15. }

       
       
       
       
  1. Intent intent=new Intent(this,SecondActivity.class);
  2. //第三种类型:这是通过字符串及其数组传递数据
  3. intent.putExtra("String","哈哈哈哈");
  4. String[] strings=new String[]{"shanghai","beijing","zhengzhou","sanmenxia"};
  5. intent.putExtra("String[]",strings);
  6. startActivity(intent);
  7. //取数据
  8. Intent intent = getIntent();
  9. if (null != intent) {
  10. String dataone=intent.getStringExtra("String");
  11. String[] datas=intent.getStringArrayExtra("String[]");
  12. }


       
       
       
       
  1. //第五种类型:这是通过bundle来进行传递数据
  2. Intent intent=new Intent(this,ThirdActivity.class);
  3. Bundle bundle=new Bundle();
  4. bundle.putString("name","秦始皇");
  5. bundle.putInt("age",2000);
  6. bundle.putBoolean("living",false);
  7. bundle.putFloat("height",165);
  8. bundle.putDouble("weight",165.66);
  9. intent.putExtras(bundle);
  10. startActivity(intent);
  11. Intent intent = getIntent();
  12. if (null != intent && null != intent.getExtras()) {
  13. Bundle bundle = intent.getExtras();
  14. tv_name.setText(getString(R.string.thirdactivity_name,(String) bundle.get("name")));
  15. tv_age.setText(getString(R.string.thirdactivity_age,(Integer) bundle.get("age")));
  16. tv_height.setText(getString(R.string.thirdactivity_height,(Float) bundle.getFloat("height")));
  17. tv_weight.setText(getString(R.string.thirdactivity_weight,(Double) bundle.getDouble("weight")+""));
  18. tv_isliving.setText(getString(R.string.thirdactivity_isLiving,(Boolean) bundle.getBoolean("living") + ""));
  19. }

        

        3.activity使用intent正向数据传递

                    即从activityA跳到activityB,此时通过intent将数据从activityA携带到activityB,这就是正想数据传递;之后从activityA返回到activityB,携带者数据,此时就叫做数据回传。

        4.activity使用intent进行数据回传

                   在进行数据会传递的时候,还是通过intent的五种携带数据的方式进行携带数据,总体来说是这样的:

                                当从actiityA跳到activityB时,然后从activityB返回到actiityA,而且需要actiivtyB向activityA回传一些数据,此时就要进行数据回传,在从actiivtyA跳转到activityB时,我们就要使用startActivityForResult(int requestCode,Intent intent)方法--其中requestCode是用于区分将来会传递的数据来自于哪个activity中,然后在activitya的onActivityResult(int ResultCode,int resultCodeIntent intent)方法中进行接受回传的数据,在activityb中的如果要回传数据的话,直接调用setResult(int resultCode,Intent intent),将数据直接封装在intent中,然后设置resultCode来区分是该activity中哪种条件下的数据(一个activity有可可能根据条件的不同,要回传不同的数。,)。


                            例子:

      
      
      
      
  1. MainActivity
  2. //这是跳转的方法
  3. private void startThirdActivity() {
  4. //第五种类型:这是通过bundle来进行传递数据
  5. Intent intent=new Intent(this,ThirdActivity.class);
  6. Bundle bundle=new Bundle();
  7. bundle.putString("name","秦始皇");
  8. bundle.putInt("age",2000);
  9. bundle.putBoolean("living",false);
  10. bundle.putFloat("height",165);
  11. bundle.putDouble("weight",165.66);
  12. intent.putExtras(bundle);
  13. startActivityForResult(intent,contants.activity_main_request_code_to_third);
  14. }
  15. private void startSecondActivity() {
  16. Intent intent = new Intent(this, SecondActivity.class);
  17. startActivityForResult(intent, contants.activity_main_request_code_to_second);
  18. }
  19. //这是接受回传数据的方法:
  20. @Override
  21. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  22. if (contants.activity_main_request_code_to_second == requestCode) {
  23. if (contants.activity_second_result_code == resultCode) {
  24. tv_third_back_data.setText(data.getStringExtra("message"));
  25. }
  26. } else if (contants.activity_main_request_code_to_third == requestCode) {
  27. if (contants.activity_third_result_code_one == resultCode) {
  28. tv_second_back_data.setText(data.getStringExtra("锄禾") + "one");
  29. } else if (contants.activity_third_result_code_two == resultCode) {
  30. tv_second_back_data.setText(data.getStringExtra("春晓") + "two");
  31. }
  32. }
  33. }

       
       
       
       
  1. //这是ThirdActivity中回传数据的操作
  2. bt_back.setOnClickListener(new View.OnClickListener() {
  3. @Override
  4. public void onClick(View v) {
  5. Intent intent=new Intent();
  6. intent.putExtra("锄禾","锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦!");
  7. setResult(contants.activity_third_result_code_one,intent);
  8. finish();
  9. }
  10. });
  11. bt_back_one.setOnClickListener(new View.OnClickListener() {
  12. @Override
  13. public void onClick(View v) {
  14. Intent intent=new Intent();
  15. intent.putExtra("春晓","春眠不觉晓,处处闻啼鸟。");
  16. setResult(contants.activity_third_result_code_two,intent);
  17. finish();
  18. }
  19. });

       
       
       
       
  1. //这是SecondActivity中回传数据时的操作
  2. bt_back_one.setOnClickListener(new View.OnClickListener() {
  3. @Override
  4. public void onClick(View v) {
  5. Intent intent=new Intent();
  6. intent.putExtra("message","this is from second activity!");
  7. setResult(contants.activity_second_result_code,intent);
  8. finish();
  9. }
  10. });

                    


四.activity的横竖屏之间的转换

                手机中一般都有重力感应,从而让屏幕进行横竖屏之间的切换,但是我们一般不常用一般为:看视频,玩游戏,签名等。

   1.设置activity的方向,有两种方式:

                    2.1第一种是在清淡文件中:

                            直接配置activity的属性:android:screenOrientation="portrait"        

                            代码如下:

      
      
      
      
  1. <activity android:name=".ThirdActivity"
  2. android:screenOrientation="portrait"/>     

                    2.2第二种是在actiity代码中:

      
      
      
      
  1. setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//这是设置竖屏
  2. setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//这是设置横屏

    2.  在横竖屏切换的时候,会触发生命周期方法,onpause()--onstop()--ondestroy()--oncreate()--onstart()--onresume()方法,注意横屏状态下该activity执行所有生命周期方法,然后在执行竖屏状态下的activity的oncreate等一系列生命周期方法,所以说当我们想要在横竖屏之间进行数据的保存与传递的时候,此时我们应该是在onstop()方法中进行保存数据,在ondestroy()方法中进行释放资源。

            2.1有一种情况,在理论上是存在的,但是在实际的开发中是不存在,我们可以通过在清单文件中配置一些activity属性,从而让actiivty在进行横竖屏转换的时候,不走该activity的生命周期方法(包括onSaveInstanceState()和onRestoreInstanceState()方法),而是走一个特定的方法即onConfigurationChanged(Configuration newConfig),而在清单文件中的配置如下:

      
      
      
      
  1. <activity android:name=".MainActivity"
  2. android:configChanges="orientation|screenSize"/>

 3.横竖屏之间的屏幕适配:

            当一个actiity在进行横竖屏之间进行切换的时候,此时该activity会使用不同的xml布局文件,当我们的项目中包含layout_land的时候,此时当横屏的时候,就会走该文件夹下的相应的布局文件;如果我们的项目文件中不包含这个layout_land的时候,此时就是使用原来的xml布局文件。

            注意:在layout和layout_land中,相应的xml布局文件的名字必须是一样的。

            

   



五.一些特定方法的特定讲解

           1.finish()方法执行了那些方法?

                   1.1 在onstop方法中调用system.exit(0) 方法,退出app,此时app就不会再走ondestroy方法;但是在onpause方法调用,app会瞬间启动    

                   1.2 当我们在oncreate方法中调用finish()方法的时候,此时activity走的生命周期就是直接oncreate--ondestroy

                   1.3 当调用finish方法的时候,一般性的会走onpause--onstop--ondestroy

           2.在各个生命周期方法,都应该做些什么?

                    2.1 oncreate()方法--做的是建立activity所需要的一些基础操作,例如:从intent中获取数据,声明ui变量,声明全局变量,设置ui控件的具体点击事件,以及一些访问网络获取数据。

                    2.2. onstart()方法--当系统调用activity的onstop方法之后,此app就会处在后台一段时间,之后走onrestart()--onstart()--onresume()方法,此时我们在onstart方法中,可以做的事情:

                            2.2.1会使一个比较好的验证某一些必须的系统特性是否可用的地方。

                            2.2.2在onpause(),onstop()方法中清除的资源,重新实例化。

                    2.3 onresume()方法--一般性不做,特殊情况下会做:

                            1.开始动画,或者只有在用户获取到焦点时才需要的组件

                            2.视频的开始播放等

                    2.4  onpause()方法--

                            当系统调用activity的onpause()方法的时候,从技术性将,activity所处的状态为可见但是不能交互的状态,在大多数情况,系统会紧接这调用activity的onstop方法,从而让activity进入到stoped状态,在这个方法中我们应该做的事:释放activity的资源,但是不做耗时的事情,耗时的事情放在onstop方法去做,如果在onpause()方法中做耗时操作的话,会使页面跳转变的很慢,不顺畅。

                            1.停止动画活着其他正在运行导致cpu消费的操作。

                            2.保存没有保存的改变。(例如邮件草稿)

                            3.释放系统资源,例如broadcast,sensors(比如gps),活着其他任何影响到电量的资源。

                            4.如果程序正在使用camera,在这个地方去做释放资源的操作。    

                            5. 视频的暂停以及播放进度。           

                    2.5 onstop()方法--

                            在该方法中可以做一些耗时操作,比如写数据到database等等。

                    2.6 ondestory()方法--

                       1 有可能导致内存泄漏的地方,做彻底的清除工作,释放资源(置空)。


六.activity保存数据和状态。

           6.1在android中用于保存和恢复数据的功能有三种形式:

                    第一种:利用activity的周期方法,进行正常的数据数据的保存和恢复。

                    第二种:利用onSaveInstanceState()和onRestoreInstanceState()方法进行瞬时数据的保存和恢复。

                    第三种: onRetainCustomNonCoonfigurationInstance()(已经被方法onRetainCustomNonConfigurationInstance()替代)和

                                 getLastNonConfigurationInstance()(被方法 getLastCustomNonConfigurationInstance()替代)--主要用于屏幕的旋转操作是保存数据

           

           6.2onSaveInstanceState( Bundle outInstance)和onRestoreInstanceState(Bundle oncreateInstance)方法:

                    这两个方法并不是activity的生命周期方法,所以只有一些特定的情况下才会执行这两个方法。其中onSaveInstanceState(Bundle outState)是用于保存要恢复的数据,而onRestoreInstanceState(Bundle oncreateState)则是用于恢复已经保存的数据,由于我们要保存的数据均保存在Bundle对象中,也就是基本上是键值对的形式来保存的,两个方法一般性都是保存一些瞬时数据。

                6.2.1###onSaveInstanceState()方法什么时候调用:

                    该方法执行的具体时间为:在onPause()之后, onStop()之前。

                    当应用遇到一些情况,在这些情况下,该应用的activity有可能被系统杀死。那么这些情况下,系统会调用onSaveInstanceState()方法,例如:

                    <1>当用户按下home键的时候。

                                当用户按下home键的时候,此时一般手机会回到首页,然后用户有可能会运行其他别的程序,那切换到后台的程序A的activity就有可能因为系统内存不足,从而有可能被系统杀死。

                    <2>当用户长按home键的时候,选择其他正在运行的程序。

                    <3>关闭屏幕显示即锁屏(或者按下电源键)的时候

                    <4>从activityA跳转到别的activity的时候,此时activityA的onSaveInstanceState会执行。

                    <5>屏幕方向发生切换。例如从横竖屏进行切换的时候。

                6.2.2 ###onRestoreInstanceState()方法什么时候调用:

                            切记:当用户按下back键,销毁一个activitiy的时候,此时这个activity是不会执行这个方法的。

                            这个方法执行的具体时间为:onStart()之后,onresume()方法之前。

                    <1>横竖屏切换的时候

                    <2>当activityA被系统自己销毁(非用户自愿,比如系统内容不够时,杀死该activity)了,那么重建activityA的时候,就会执行。                 

                 6.2.3###onSaveInstanceState()方法的“默认实现”实现了了什么东西-“自定义实现”实现的是什么

                            当我们没有覆盖onsaveinsantcestate()方法,此方法的默认实现会自动保存activity的某些状态数据,比如activity中各种ui控件的状态,然后在需要恢复的时候,进行恢复保存的状态和数据,但是对此ui空间有要求:

                                       <1>必须是android系统框架中的ui控件(因为他们都恰当的实现了onSaveInstanceState()方法)

                                       <2>此ui控件必须指定id(系统保存ui控件状态和数据的时候,需要,否则不行的)

                            这些东西和我们的目的不向对,所以说我们只需要继承默认实现就行了。那么我们“自定义实现”实现的是什么呢?我们自定义的全局变量的值+自定义控件的状态和值等等。

                  6.2.4onSaveInstanceState()和 onRetainCustomNonCoonfigurationInstance()之间的区别

                           上述两种方法均可以达到保存和恢复数据的功能,而且前者的保存的数据更多(有系统自愿的默认保存),那后者为什么存在呢?这两种方法保存的数据的区别:

                        <1>onSaveInstanceState()存储的数据是保存在bundle对象中的,数据不能太大,且以键值对为宜; onRetainCustomNonCoonfigurationInstance()返回的object类型,可以保存任意类型的对象,不关乎大或者小,比如AsyncTask,SQLiteDataBase,Bitmap,socket等。                                  



七.activity在清单文件中的配置详解以及例子:

例子1:一个application配置两个入口:

                activity应用配置两个入口

        一、这种情况出现的几率不大但是会出现,比如手机上的联系人和拨号就是同一个应用的两个入口(华为mate9现在就是)。

        二、说一下原理:

        一般来说一个应用只有一个入口,在清淡文件中,节点中,选择其一些参数进行配置应用的图标和名字:

      
      
      
      
  1. <application
  2. android:allowBackup="true"
  3. //这是应用的icon图标
  4. android:icon="@mipmap/ic_launcher"
  5. //这时应用的名字
  6. android:label="@string/app_name"
  7. android:supportsRtl="true"
  8. android:theme="@style/AppTheme">
  9. <activity android:name=".MainActivity"
  10. android:screenOrientation="portrait"
  11. android:launchMode="singleTop">
  12. <intent-filter>
  13. <action android:name="android.intent.action.MAIN" />
  14. <category android:name="android.intent.category.LAUNCHER" />
  15. intent-filter>
  16. activity>
  17. application>
        但是当我们需要一个应用有两个入口的时候,直接在app的清单文件中配置两个activity为应用的入口即可。
       将一个activity配置成为应用的入口,只需要配置一个这个意图过滤器,需要指定date和category为特定的类型:

      
      
      
      
  1. <activity android:name=".MainActivity"
  2. //应用的名字
  3. android:label="@string/app_name_one"
  4. //应用的图标
  5. android:icon="@drawable/ic_launcher_haofuli">
  6. <intent-filter>
  7. <action android:name="android.intent.action.MAIN" />
  8. <category android:name="android.intent.category.LAUNCHER" />
  9. intent-filter>
  10. activity>
          当我们需要让两个入口显示不同的图标和名字的时候,直接配置activity的属性icon和label即可(此时在界面中出现的应用的图标和名字就是activity配置的图标和名字,但是在android的进程中该app显示的名字和图标是application的配置项中的名字和图标),如上图中activity的属性label和icon。


你可能感兴趣的:(android学习笔记)