1、简介

该文记录了本人在活动开发中遇到的诸多问题。现在开发中主要遇到的是,开发上的活动栈处理,以及一些主题设置相关的总结处理。

2、启动模式

活动栈

主要分析下:SingleTop 和 singleTask 这2种启动模式[当然一共有四种启动模式:还包括singleInstance以及标准启动

singleTop: 栈顶复用模式,如果新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时它的 onNewIntent方法会被回调。

singleTask:栈内复用模式,这是一种单实例模式,在这种模式下,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,和singleTop一致,,系统也会回调onNewIntent。如果不存在,系统会先寻找是否存在需要的栈,如果不存在该栈,就创建一个任务栈,并把该Activity放进去;如果存在,就会创建到已经存在的栈中

singleTask用途: 同个Activity实例在栈中只有一个,即不存在重复创建;可通过android:taskAffinity设定该Activity需要的任务栈,即可能会引起任务栈的变更;常用于主页和登陆页

<activity
            android:name=".improve.main.MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:screenOrientation="portrait"
            android:theme="@style/App.Theme.Main" />

代码中设置的启动模式要比xml中设置的启动模式的优先级更高。

a-标准

标准模式 A-B-C-D-B-C

com.example.mydairytestproject E/Strand启动模式: ActivityA onCreate()
com.example.mydairytestproject E/Strand启动模式: ActivityB onCreate()
com.example.mydairytestproject E/Strand启动模式: ActivityC onCreate()
com.example.mydairytestproject E/Strand启动模式: ActivityD onCreate()
com.example.mydairytestproject E/Strand启动模式: ActivityB onCreate()
com.example.mydairytestproject E/Strand启动模式: ActivityC onCreate()
com.example.mydairytestproject E/Strand启动模式: ActivityC onDestroy()
com.example.mydairytestproject E/Strand启动模式: ActivityB onDestroy()
com.example.mydairytestproject E/Strand启动模式: ActivityD onDestroy()
com.example.mydairytestproject E/Strand启动模式: ActivityC onDestroy()
com.example.mydairytestproject E/Strand启动模式: ActivityB onDestroy()
com.example.mydairytestproject E/Strand启动模式: ActivityA onDestroy()

b-singleTop

在mainfest的活动中注册!

<activity android:name=".task.ActivityB"
            android:launchMode="singleTop"/>

当B C存在栈内但不位于栈顶是打印信息如下:

com.example.mydairytestproject E/SingleTop启动模式: ActivityA onCreate()
com.example.mydairytestproject E/SingleTop启动模式: ActivityB onCreate()
com.example.mydairytestproject E/SingleTop启动模式: ActivityC onCreate()
com.example.mydairytestproject E/SingleTop启动模式: ActivityD onCreate()
com.example.mydairytestproject E/SingleTop启动模式: ActivityB onCreate()
com.example.mydairytestproject E/SingleTop启动模式: ActivityC onCreate()
com.example.mydairytestproject E/SingleTop启动模式: ActivityC onDestroy()
com.example.mydairytestproject E/SingleTop启动模式: ActivityB onDestroy()
com.example.mydairytestproject E/SingleTop启动模式: ActivityD onDestroy()
com.example.mydairytestproject E/SingleTop启动模式: ActivityC onDestroy()
com.example.mydairytestproject E/SingleTop启动模式: ActivityB onDestroy()
com.example.mydairytestproject E/SingleTop启动模式: ActivityA onDestroy()

 A-B-B是信息如下:

com.example.mydairytestproject E/SingleTop启动模式: ActivityA onCreate()
com.example.mydairytestproject E/SingleTop启动模式: ActivityB onCreate()
com.example.mydairytestproject E/SingleTop启动模式: ActivityB onNewIntent
com.example.mydairytestproject E/SingleTop启动模式: ActivityB onDestroy()
com.example.mydairytestproject E/SingleTop启动模式: ActivityA onDestroy()

在代码中书写如下: 

Intent intent = new Intent(ActivityB.this, ActivityB.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
com.example.mydairytestproject E/SingleTop启动模式: ActivityA onCreate()
com.example.mydairytestproject E/SingleTop启动模式: ActivityB onCreate()
com.example.mydairytestproject E/SingleTop启动模式: ActivityB onCreate()
com.example.mydairytestproject E/SingleTop启动模式: ActivityB onDestroy()
com.example.mydairytestproject E/SingleTop启动模式: ActivityB onDestroy()
com.example.mydairytestproject E/SingleTop启动模式: ActivityA onDestroy()

发现了吧,在对于栈顶复用模式,只能在xml中进行设定,那样才会new出一个实例,而调用标志则只是先清除再重新创建罢了

c-singleTask

A-B-C-D-B-C 效果如下

可以发现 D-B的过程中,位于B的栈上面的C,D都是先退出了。(栈内复用,但是位于其上的活动都结束了)

com.example.mydairytestproject E/SingleTask启动模式: ActivityA onCreate()
com.example.mydairytestproject E/SingleTask启动模式: ActivityB onCreate()
com.example.mydairytestproject E/SingleTask启动模式: ActivityC onCreate()
com.example.mydairytestproject E/SingleTask启动模式: ActivityD onCreate()
com.example.mydairytestproject E/SingleTask启动模式: ActivityC onDestroy()
com.example.mydairytestproject E/SingleTask启动模式: ActivityB onNewIntent
com.example.mydairytestproject E/SingleTask启动模式: ActivityD onDestroy()
com.example.mydairytestproject E/SingleTask启动模式: ActivityC onCreate()
com.example.mydairytestproject E/SingleTask启动模式: ActivityC onDestroy()
com.example.mydairytestproject E/SingleTask启动模式: ActivityB onDestroy()
com.example.mydairytestproject E/SingleTask启动模式: ActivityA onDestroy()

java代码中设置 

Intent intent = new Intent(ActivityD.this, ActivityB.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

很带怪,怎么没效果呢,我擦! 应该是任务栈不一样。 

com.example.mydairytestproject E/SingleTask启动模式: ActivityA onCreate()
com.example.mydairytestproject E/SingleTask启动模式: ActivityB onCreate()
com.example.mydairytestproject E/SingleTask启动模式: ActivityC onCreate()
com.example.mydairytestproject E/SingleTask启动模式: ActivityD onCreate()
com.example.mydairytestproject E/SingleTask启动模式: ActivityB onCreate()
com.example.mydairytestproject E/SingleTask启动模式: ActivityC onCreate()
com.example.mydairytestproject E/SingleTask启动模式: ActivityC onDestroy()
com.example.mydairytestproject E/SingleTask启动模式: ActivityB onDestroy()
com.example.mydairytestproject E/SingleTask启动模式: ActivityD onDestroy()
com.example.mydairytestproject E/SingleTask启动模式: ActivityC onDestroy()
com.example.mydairytestproject E/SingleTask启动模式: ActivityB onDestroy()
com.example.mydairytestproject E/SingleTask启动模式: ActivityA onDestroy()

拓展内容

下面针对手动设置flg做个小结

// 栈内复用,但是重新创建

12-02 14:16:07.004 19306-19306/com.example.mydairytestproject E/启动模式: 活动A onCreate
12-02 14:16:10.505 19306-19306/com.example.mydairytestproject E/启动模式: 活动B onCreate
12-02 14:16:12.850 19306-19306/com.example.mydairytestproject E/启动模式: FLAG_ACTIVITY_CLEAR_TOP
12-02 14:16:12.892 19306-19306/com.example.mydairytestproject E/启动模式: 活动A onDestroy
12-02 14:16:12.917 19306-19306/com.example.mydairytestproject E/启动模式: 活动A onCreate
12-02 14:16:13.281 19306-19306/com.example.mydairytestproject E/启动模式: 活动B onDestroy

12-02 14:17:12.030 19306-19306/com.example.mydairytestproject E/启动模式: 活动A onDestroy

FLAG_ACTIVITY_CLEAR_TOP

清除包含目标 Activity 的任务栈中位于该 Activity 实例之上的其他 Activity 实例。 但是是复用已有的目标 Activity,还是先删除后重建,则有以下规则:

  • 若是使用 FLAG_ACTIVITY_SINGLE_TOP 和 FLAG_ACTIVITY_CLEAR_TOP 标志位组合,那么不管目标 Activity 是什么启动模式,都会被复用。
  • 若是单独使用 FLAG_ACTIVITY_CLEAR_TOP,那么只有非 standard 启动模式的目标 Activity 才会被复用,否则都先被删除,然后被重新创建并入栈。

// 这就是标准的 singletop模式

12-02 14:18:38.285 19306-19306/com.example.mydairytestproject E/启动模式: 活动A onCreate
12-02 14:18:41.761 19306-19306/com.example.mydairytestproject E/启动模式: 活动B onCreate
12-02 14:18:44.523 19306-19306/com.example.mydairytestproject E/启动模式: FLAG_ACTIVITY_SINGLE_TOP
12-02 14:18:44.560 19306-19306/com.example.mydairytestproject E/启动模式: 活动A onCreate

12-02 14:19:29.806 19306-19306/com.example.mydairytestproject E/启动模式: 活动A onDestroy

12-02 14:19:49.423 19306-19306/com.example.mydairytestproject E/启动模式: 活动B onDestroy

12-02 14:20:01.384 19306-19306/com.example.mydairytestproject E/启动模式: 活动A onDestroy

 // 结合起来才是我们标准的singleInstance模式

12-02 14:20:44.454 19306-19306/com.example.mydairytestproject E/启动模式: 活动A onCreate
12-02 14:20:45.711 19306-19306/com.example.mydairytestproject E/启动模式: 活动B onCreate
12-02 14:20:47.058 19306-19306/com.example.mydairytestproject E/启动模式: Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP
12-02 14:20:47.083 19306-19306/com.example.mydairytestproject E/启动模式: 活动A onNewIntent
12-02 14:20:47.417 19306-19306/com.example.mydairytestproject E/启动模式: 活动B onDestroy

12-02 14:20:58.629 19306-19306/com.example.mydairytestproject E/启动模式: 活动A onDestroy

FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK 标志位组合启动活动A 时,首先会清空活动A 所在的任务栈,然后再创建新的 IntentFlagTestActivity 实例并入栈

Intent intent = new Intent(LaunchBActivity.this,LaunchAActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
12-02 14:34:37.918 20378-20378/com.example.mydairytestproject E/启动模式: MainActivity onCreate
12-02 14:34:45.389 20378-20378/com.example.mydairytestproject E/启动模式: 活动A onCreate
12-02 14:34:46.565 20378-20378/com.example.mydairytestproject E/启动模式: 活动B onCreate
12-02 14:35:04.262 20378-20378/com.example.mydairytestproject E/启动模式: MainActivity onDestroy
12-02 14:35:04.299 20378-20378/com.example.mydairytestproject E/启动模式: 活动A onDestroy
12-02 14:35:04.332 20378-20378/com.example.mydairytestproject E/启动模式: 活动A onCreate
12-02 14:35:04.625 20378-20378/com.example.mydairytestproject E/启动模式: 活动B onDestroy


12-02 14:35:26.170 20378-20378/com.example.mydairytestproject E/启动模式: 活动A onDestroy

 FLAG_ACTIVITY_NEW_TASK

 Android Intent.FLAG_ACTIVITY_NEW_TASK的个人理解

当非Activity启动活动时需要加入标志 Intent.FLAG_ACTIVITY_NEW_TASK

 contextImpl 内

@Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }

   Activity 内

@Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

 

跨应用调用活动

public void openOtherActivity(View view) {
        Intent intent = new Intent();
        ComponentName componentName = new ComponentName("com.zxl","com.zxl.MainActivity");
        intent.setComponent(componentName);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.example.mydairytestproject");
launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             launchIntent.setClassName("com.example.apple.scrolldemo","com.example.apple.scrolldemo.MainActivity");
startActivity(launchIntent);


3. 意图以及匹配

至于显式的意图比较常见,就不在累赘了,这里主要想提及以下隐式的意图。IntentFilter中的过滤信息有action category和data。匹配时需要完全匹配这三者,一个过滤列表中,action category data可以有多个。一个intent只要能匹配一组filter那么就能够执行跳转。下面将通过案例来进行解释。

案例1

描述:只有一组intent-filter 且action,categoty,data 各一个,只是我们全匹配,发现跳转正确。当缺少任何一个过滤即发生崩溃。

<activity android:name=".LocationActivity">
            <!-- 案例1-->
            <intent-filter >
                <action android:name="com.zxl.location" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain"/>
            </intent-filter>
        </activity>
void jumpToLocationAvy(){
        Intent intent = new Intent();
        intent.setAction("com.zxl.location");
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        // 类型----
        intent.setType("text/plain");
        startActivity(intent);
    }


// 结果
E/IntentFtActivity: 执行跳转
E/LocationActivity: onStart: 活动跳转进来了

案例2
            在案例1的基础上在 filter多增加一个action,其余条件不变,再次运行,运行正常。

<activity android:name=".LocationActivity">
            <!--案例2-->
            <intent-filter >
                <action android:name="com.zxl.test"/>
                <action android:name="com.zxl.location" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain"/>
            </intent-filter>
        </activity>

 案例3


<activity android:name=".LocationActivity">
            <!--案例3-->
            <intent-filter >
                <action android:name="com.zxl.test"/>
                <action android:name="com.zxl.location" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.zxl.filter"/>
            </intent-filter>
        </activity>
void jumpToLocationAvy(){
        Intent intent = new Intent();
        intent.setAction("com.zxl.filter");
        startActivity(intent);
    }

// ---------系统崩溃----------

   案例4

在filter增加一个category就可以了,哈哈,机智啊。

<activity android:name=".LocationActivity">
            <!--案例4-->
            <intent-filter >
                <action android:name="com.zxl.test"/>
                <action android:name="com.zxl.location" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.zxl.filter"/>
                <!--*******重点******-->
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>


// 下面可加可不加 默认就是这个
//intent.addCategory(Intent.CATEGORY_DEFAULT);

案例5

又增加一个 category发现也是运行正确

<activity android:name=".LocationActivity">
            <!--案例5-->
            <intent-filter >
                <action android:name="com.zxl.test"/>
                <action android:name="com.zxl.location" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.zxl.filter"/>
                <category android:name="android.intent.category.DEFAULT" />
                <!-- 又增加一个category-->
                <category android:name="com.zxl.category"/>
            </intent-filter>
        </activity>

4. 其他使用技巧

4.1 应用位于后台

/**
     * 主界面按返回键不退出 而是位于后台
     * 这时候应用进来还是位于当前界面,而不会重新启动
     * @param keyCode
     * @param event
     * @return
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            moveTaskToBack(false);
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

4.2. 关于生命周期

可以明确的是,A 启动一个正常的B  应用的时候生命周期方法是这样执行的,A  onPause()  ----->  A onStop()     然后是B 的生命周期,紧接着回退活动,A的生命周期方法执行的是  A onRestart() ------> A onStart() ------> onResume(),之前我存在一个误区,经测试 活动启动一个Dialog 其实是不会回调生命周期的

MainActivity 跳转 => ActivityA 生命周期回调

2019-12-06 10:58:57.834 2063-2063/com.example.mydairytestproject E/启动: MainActivity onPause: 
2019-12-06 10:58:58.147 2063-2063/com.example.mydairytestproject E/启动: ActivityA onCreate: 
2019-12-06 10:58:58.155 2063-2063/com.example.mydairytestproject E/启动: ActivityA onStart: 
2019-12-06 10:58:58.157 2063-2063/com.example.mydairytestproject E/启动: ActivityA onResume: 
2019-12-06 10:58:58.886 2063-2063/com.example.mydairytestproject E/启动: MainActivity onStop:

那特殊的情况启动一个透明应用,生命周期略有不同,这一点相比大家都是知道的,我这里也进行一一番验证吧。A启动一个透明应用的话, 那么A 首先会执行 onPause() 方法,紧接着当A 回退时执行的是 onResume() 方法。

08-31 09:30:49.361 25312-25312/com.example.zxl.myworklearning E/生命周期: ---onPause()---
08-31 09:30:55.300 25312-25312/com.example.zxl.myworklearning E/生命周期: ---onResume()---

记录下如何设置透明应用,需要在style里加入如下属性 

<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>

onSaveInstanceState() 会在Activity被异常终止的情况下调用,调用在onStop()之前,通过bundle 可在onRestoreInstanceState( ) 和 onCreate( ) 方法中接收并处理,达到恢复活动的效果,onResoreInstanceState( ) 是在onStart( )之后调用的

android:configChanges = "orientation"  : 代表的是不让Activity在屏幕旋转的时候重新创建,指定了该属性后是不会重新创建活动的,但是会调用 onConfigChaned( )方法。

4.3. 活动启动动画

1. 默认效果

当正常启动一个活动默认的动画效果是右边的活动从右到左进来,退出的时候从左往右回去

2. 如何不带动画效果的启动一个活动呢

A. 使用theme主题

如下实例为不带任何效果启动一个activity

// mainfest进行主题设置
<activity android:name=".TopViewActivity"
          android:theme="@style/TopViewTheme">
</activity>

styles定义主题样式

android:windowAnimationStyle 可针对应用于该theme的活动的上的切换动画方式。

<style name="TopViewTheme" parent="AppTheme">
        // 改变整个应用的切换方式    
        <item name="android:windowAnimationStyle">@style/ActivityAnimation</item>
    </style>
    
    <!--指定activity动画-->
    <style name="ActivityAnimation">
        <item name="android:activityOpenEnterAnimation">@null</item>
        <item name="android:activityOpenExitAnimation">@null</item>
        <item name="android:activityCloseEnterAnimation">@null</item>
        <item name="android:activityCloseExitAnimation">@null</item>
        <item name="android:taskOpenEnterAnimation">@null</item>
        <item name="android:taskOpenExitAnimation">@null</item>
        <item name="android:taskCloseEnterAnimation">@null</item>
        <item name="android:taskCloseExitAnimation">@null</item>
        <item name="android:taskToFrontEnterAnimation">@null</item>
        <item name="android:taskToFrontExitAnimation">@null</item>
        <item name="android:taskToBackEnterAnimation">@null</item>
        <item name="android:taskToBackExitAnimation">@null</item>
    </style>

ok,如上就完成了如何不带任何样式启动一个活动的例子。

不动神色的返回

overridePendingTransition 常用于优雅的对活动进行切换

public void overridePendingTransition(int enterAnim, int exitAnim) {
        try {
            ActivityManagerNative.getDefault().overridePendingTransition(
                    mToken, getPackageName(), enterAnim, exitAnim);
        } catch (RemoteException e) {
        }
    }

 对即将要退出栈的活动,重写其finish方法,让其退出时不执行任何动画效果。 

@Override
    public void finish() {
        super.finish();
        overridePendingTransition(0,0);
    }

4.4. 理解ContextImpl

public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

        Application app = null;

        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "initializeJavaContextClassLoader");
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            
            // 后面会执行绑定的.....
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            }
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;

        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!instrumentation.onException(app, e)) {
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
        }

        // Rewrite the R 'constants' for all library apks.
        SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
        final int N = packageIdentifiers.size();
        for (int i = 0; i < N; i++) {
            final int id = packageIdentifiers.keyAt(i);
            if (id == 0x01 || id == 0x7f) {
                continue;
            }

            rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
        }

        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        return app;
    }

 

Instrumentation
static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }

4.5. 页面跳转规则 -> 先跳转再finish

startActivity(new Intent(LoadingActivity.this, MainActivity.class));
overridePendingTransition(R.anim.screen_zoom_in, R.anim.screen_zoom_out);
finish();

讲述下页面跳转的原则,启动一个活动,设置动画。如果需要结束那么执行finish。

切记 千万不能先finish再进行跳转,否则会出现抖现黑屏的问题。原则上我们还是先执行任务再finish吧,当然即便你先finish,那么这一块都执行完了之后才onDestory()的。

 

通过一个小案例,我们来看下finish的用途,虽然我在程序一开始的时候就执行了finish,那么会去执行finish方法,然而他确是等onCreate()执行完毕才去调用了 onDestory()的,这里我们记一下。

同样点击事件也是一样,方法块执行完毕之后才到生命周期onDestory中去。

E/finish: finish: 
E/finish: 结束完毕
E/finish: actionViews: 
E/finish: onCreate:完毕
E/finish: onDestroy: 
E/finish: run: 0
E/finish: run: 1
E/finish: run: 2
E/finish: run: 3
E/finish: run: 4
...
E/finish: run: 9
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bg);
        finish();
        Log.e(TAG, "结束完毕" );
        ...
        new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        for (int i=0;i<10;i++){
                            try {
                                Thread.sleep(100);
                                Log.e(TAG, "run: "+i);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
        ).start();
        Log.e(TAG, "onCreate:完毕");
    }