Android 活動小結

1、簡介

該文記錄了本人在活動開發中遇到的諸多問題。現在開發中主要遇到的是,開發上的活動棧處理,以及一些主題設置相關的總結處理。

2、啓動模式

活動棧

主要分析下:SingleTopsingleTask 這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);
            }
        }
    }

  不錯的startActivity文章

 

跨應用調用活動

    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);

Android中通過外部程序啓動App三種方式 

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. 其他使用技巧

    /**
     * 主界面按返回鍵不退出 而是位於後臺
     * 這時候應用進來還是位於當前界面,而不會重新啓動
     * @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);
    }

5. 關於生命週期

可以明確的是,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( )方法。

6. 活動啓動動畫

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);
    }

7. 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;
    }

8. 頁面跳轉規則

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

講述下頁面跳轉的原則,啓動一個活動,設置動畫。如果需要結束那麼執行finish。

切記 千萬不能先finish再進行跳轉,否則會出現抖現黑屏的問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章