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:完毕");
}