Avtivity 知识点,不断更新中

**

原创,转载请在文章首部标明本地址

**

Avtivity 知识点,不断更新中

一、Activity是什么 ?

二、Activity 生命周期

三、Activity 启动方式(android:launchMode)


  1. standard 标准模式

系统默认模式,每次启动ACtivity,不管该Activity的实例是否存在,都会创建一个新的实例。该Activity与启动它的Activity属于同一个任务栈

注意:applicationContext不可启动standard模式的Activity。因为非Activity的context类型没有任务栈,那么如果要启动该模式的Activity,那该Activity无法进入任务栈,那么该Activity就不属于任何任务栈。

  • singleTop

    栈顶复用模式。如果将要启动的Activity**处于任务栈的顶部,那么该Activity会直接复用栈顶的实例。因为该Activity的实例已经存在,那么便不会执行onCreate和onStart,但会调用**onNewIntent方法。在onNewIntent中可以取出这次请求的信息。但是如果该Activity不在任务栈的顶部,则会新建该Activity的实例。

  • singleTask

    栈内复用模式。如果即将启动的Activity在某个任务栈中存在,则直接复用该Activity实例。再次过程中,只会执行onNewIntnent。具体而言,当存在该Activity所需要的任务栈,那么在该任务栈中查找该Activity的实例,如果查找到则直接复用,否则新建该Activity的实例并入栈。如果不存在该Activity的任务栈,则新建一个任务栈,然后新建Activity实例,并入栈。

    注意:当栈内复用时,那么将会把栈内该Activity之上的所有实例出栈。

  • singleInstance

    单例模式。如果某个Activity为该模式,那么该Activity只能单独的存在于某一个任务栈中,其他特征与singleTask相同。


  • 注意: 上述任务栈是由taskAffinity属性来判定的,默认情况下所有的Activity的taskAffinity属性都是应用包名。如果想指定某个Activity所在的任务栈,修改该属性即可。该属性仅仅在于singleTask或allowTaskReparenting配合使用时才有意义。

    附:FLAF vs android:launchMode

    FLAG_ACTIVITY_NEW_TASK:singleTask

    FLAG_ACTIVITY_CLEAR_TOP: 如果该Activity在当前任务栈中存在实体,那么销毁栈中在其之上的Activity实例,然后创建一个新的实例添加到栈顶。

    FLAG_ACTIVITY_SINGLE_TOP: singleTop

    总结:使用FLAG则不支持singleInstance,使用android:launchMode则不支持CLEAR_TOP

    四、task字段说明

    1. Android:allowTaskReparenting

      该属性用来标记当Activity退居后台之后,是否能从启动它的Activity所在的任务栈移动到与它有相同taskAffinity的任务栈。eg:在应用中页面A启动了浏览器,那么此时打开的浏览器页面B与A是属于同一个任务栈的,当B退居后台之后,B就会移动到浏览器所在的任务栈中,并且处于该栈的顶部,所以当再次打开浏览器的时候,显示的是页面B。

    2. android:allowRetainTaskState

      该属性用来标记是否能够保持原有的状态,但是该属性仅仅只对根Activity起作用(所谓根Activity一般指app的主页面)。

    3. android:clearTaskOnLaunch
      如果该属性为true,那么当启动该Activity时,便会清除该Activity所在任务栈的其他所有Activity。
    4. android:finishOnTaskLaunch
      如果设置该属性为true,那么点击home键回到屏幕之后,再次点击应用图标进入引用之后,系统自动销毁该Activity。
    5. android:alwaysRetainTaskState
      如果当前任务栈的根Activity的该属性设置为true,在该任务栈stop之后仍然保持该任务栈中所有Activity的状态。

    四、启动系统Activity

    1. 启动浏览器:

    五、数据交互

    六、系统配置变化导致的Activity变化

    1. Device Configurations

    Orientation, Keyboard, Language.

    2. 原理简介及解决方案

    一般情况下,当Device Configuration 在Application运行时发生变化,那么系统会自动重启该Activity(此时先onSaveInstance保存数据,然后执行onDestroy,最后执行onCreate)。

    所以我们必须在Activity销毁之前使用onSaveInsance保存数据,在onCreate或者onRestoreInsanceState中回复数据,以此来提供良好的用户体验。但是有时,我们需要保存大量的数据,遇到这种情况一般有两种解决方案:

    a. 引用对象

    由于在回调onSaveInstanceState保存的数据不适合保存大批量的数据对象(例如bitmap),而且保存的数据对象必须是Serialized的。这种情况下,当系统配置发送变化时,我们通过引用Fragment来保存数据,在fragment中保存数据对象。具体实现如下:

    //注意:当保存数据时,千万不要保存任何引用Activity实例的对象,否则会造成内存泄漏
    
    public class RetainedFragment extends Fragment {
    
            // data object we want to retain
            private MyDataObject data;
    
            // this method is only called once for this fragment
            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                // retain this fragment
                setRetainInstance(true);**重点内容**
            }
    
            public void setData(MyDataObject data) {
                this.data = data;
            }
    
            public MyDataObject getData() {
                return data;
            }
        }

    然后使用FragmentManager将fragment添加到Activity中。

    public class MyActivity extends Activity {
    
            private RetainedFragment dataFragment;
    
            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
    
                // find the retained fragment on activity restarts
                FragmentManager fm = getFragmentManager();
                dataFragment = (DataFragment) fm.findFragmentByTag(“data”);
    
                // create the fragment and data the first time
                if (dataFragment == null) {
                    // add the fragment
                    dataFragment = new DataFragment();
                    fm.beginTransaction().add(dataFragment, “data”).commit();
                    // load the data from the web
                    dataFragment.setData(loadMyData());
                }
    
                // the data is available in dataFragment.getData()
                ...
            }
    
            @Override
            public void onDestroy() {
                super.onDestroy();
                // store the data in the fragment
                dataFragment.setData(collectMyLoadedData());
            }
        }

    >
    b. 自己处理系统配置变化引起的改变

    当系统配置发生变化时,如果Activity不需要更新数据或自动应用资源,那么可以声明自己处理该配置变化。

    首先,在AndroidManifest中作如下声明:

    <activity android:name=".MyActivity"
                  <-- 在此处定义自己要处理的变化-->
                  android:configChanges="orientation|keyboardHidden"
                  android:label="@string/app_name">

    当在xml中声明的任意配置发生变化时,系统不会自动重启该Activity,此时系统将回调onConfigurationChanged()。

    注意: 当App的targetSdkVersion大于等于13,如果您想处理屏幕方向切换配置变化,那么你必须在android:configuration中包含screenSize属性。

    七、启动过程

    1. 相关类:

    Instrumentation, ActivityThread, ActivityManagerService。

    2. 过程分析:

    当用户启动Activity时,Instrumentation会接收该请求,然后instrumentation利用Binder向ActivityManagerService发请求。ActivityManagerService内部维护者Activity的调用堆栈(ActivityStack)及各个Activity的状态同步,ActivityManagerService通过ActivityThread去管理Activity的状态从而完成Activity的生命周期的管理。

    八、关于AndroidManifest所需要知道的一切

    你可能感兴趣的:(android,Activity,task)