一篇好文之 关于Activity你应该知道的一切

前言

工作好几年了,也没留下什么!所以想写点什么,算是对自己技术的一个总结,同时也希望给后来的Android开发学习者一些简单的参考。

老套路,有关Activity 的任何问题,欢迎在文章末尾或者我的公众号「aserbao」留言。知无不言…… 先看效果图(文末有源码地址):
activityOverridePendingTransition在这里插入图片描述在这里插入图片描述

为什么写这篇文章?

Activity 是所以Android 初学者最先接触,也是必不可少需要接触的一个类,所以,作为 Android 学习系列的第一篇再好不过,别无其他理由。这是作为Activity系列最简单的一篇,只要不是初学者均可跳着看。

什么是Activity?Activity 用来做什么?

Activity 是Android中的一个活动窗口,Activity类主要负责在Android中创建一个与用户交互的窗口。

Activity的生命周期

能用图说明的坚决不用文字,一起看图。
在这里插入图片描述

  • onCreate(): onCreate() 方法在Activity创建的时候就会调用,且整个Activity生命周期中有且只调用一次。
  • onStart():在onCreate方法或者onRestart()方法之后调用,这个状态下Activity准备进入前台可交互状态。
  • onResume(): 在onStart()方法之后被调用,此时Activity已进入可交互状态。我们也可以叫他为恢复状态。这个方法的调用通常是作为开始动画,打开相机的绝佳位置。这个方法并不是判读当前Activity是否显示的最好标准,比如存在键盘的情况下,键盘显示了,Activity的内容还没有显示,所以最好使用onWindowFocusChanged()方法来判读Activity是否对用户可见!
  • onPause(): 当当前Activity失去焦点时,会调用此方法,网上有很多说onPause方法调用之后Activity不可见,这里要纠正一下,onStop方法之后Activity不可见,比如在多窗口情况下,onPause方法调用之后,Activity依然是完全可见状态。
  • onStop():当Activity不可见时,才会调用此方法。通常我们在此调用中进行动画暂停,CPU资源完全释放,相机关闭等操作。当Activity在onStop状态后,要让界面可见,这时候会调用onRestrat方法,要么销毁,这时候会调用onDestory方法。
  • onDestory(): onDestory的回调有两种情况:1. 活动正在结束(由于用户完全解雇活动或因活动 finish()被召唤)2.由于配置更改(例如设备旋转或多窗口模式),系统暂时销毁活动。在此方法回调时,我们应该清除任何Activity数据。此方法是Activity接收的最后一个生命周期的回调。

Activity的创建

当我们通过Android Studio 创建项目的时候,项目会默认为我们创建一个MainActivity 的类,也就是我们的主界面。这篇文章主要讲Activity学习的第一步,Activity 的创建。

  1. 在项目中需要创建Activity的目录右击。
  2. 点击New
  3. 点击Activity
  4. 这里有很多系统配置好的Activity供我们选择,如果没有特殊要求就选Empty Activity。
    在这里插入图片描述

Activity的启动方法

当启动Activity不需要回调我们可以调用 startActivity()方法,若需要从跳转的Activity返回数据,则通过调用startActivityForResult(~)来进行跳转,并将其传递给描述您想启动的 Activity 的 Intent 来启动另一个 Activity
我们可以通过startActivity() 来启动Activity,并且可以通过Activity 的Intent为跳转的Activity 提供少量的数据。

Intent intent = new Intent(this, LifeCycleActivity.class);
startActivity(intent);

我们也可以通过startActivityForResult(Intent intent, int requestCode)来启动Activity,这种方式启动可以获取跳转Activity退出后回传的结果数据。

Intent intent = new Intent(this, LifeCycleActivity.class);
startActivityForResult(intent,0);

当然,还有startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options)方法,我们在后面的Activity过渡动画界面会讲到。

Activity 的启动模式

  1. standard
    标准模式(也是Android默认的启动模式),在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。

    例如: 若我有一个Activity名为A1, 上面有一个按钮可跳转到A1。那么如果我点击按钮,便会新启一个Activity A1叠在刚才的A1之上,再点击,又会再新启一个在它之上…… 点back键会依照栈顺序依次退出。(你启动多少个Activity,你就需要点击多少下返回键才能回主界面。)

  2. singleInstance
    单例模式,整个项目中有切只会存在一个Activity实例。当第二次调用的时候不会走Activity的onCreate()方法,会调用onNewIntent()方法。

    例如:Task栈1的情况为:A B C。C通过Intent跳转到D,而D的Launch mode为singleInstance,则将会新建一个Task栈2。此时Task栈1的情况还是为:A B C。Task栈2的情况为:D。此时屏幕界面显示D的内容,如果这时D又通过Intent跳转到D,则Task栈2中也不会新建一个D的实例,而是调用D的onNewIntent()方法,所以两个栈的情况也不会变化。而如果D跳转到C,则栈1的情况变成了:A B C C,因为C的Launch mode为standard,此时如果再按返回键,则栈1变成:A B C。也就是说现在界面还显示C的内容,不是D。 按返回键,则栈1变成:A B C。也就是说现在界面还显示C的内容,不是D。

  3. singleTop
    栈顶复用模式,singleTop英文记忆,只有Activity在栈顶,才不会创建Activity的实例,会调用当前Activity 的onNewIntent()方法。若Activity不在栈顶,则和standard的启动模式一样。

    例如:Task栈1中存在Activity A,B,C,若C的启动模式为singleTop,则从C跳转到C不会新建Activity实例,而是调用原先栈顶的C onNewIntent()方法。若B为SingleTop,C为standard,则从C跳转至B则会重新创建C的实例。

  4. singleTask
    栈内复用模式,singleTask 和singleInstance一样,均只有一个实例。不同点在于:在同一个应用程序中启动他的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent()方法。 如果是在别的应用程序中启动它,则会新建一个task,并在该task中启动这个Activity,singleTask允许别的Activity与其在一个task中共存,也就是说,如果我在这个singleTask的实例中再打开新的Activity,这个新的Activity还是会在singleTask的实例的task中。

  5. 属性taskAffinity
    我们可以在manifest文件中对Activity进行taskAffinity属性配置,如:

     <activity
                android:name=".aaSource.android.app.Activity.launchMode.SingleTopActivity"
                android:taskAffinity="com.aserbao.aserbaosandroid.otherTask" 
                android:launchMode="singleTop"
                android:screenOrientation="portrait" />
    

    具有相同taskAffinity值的Activity我们可以看做在一个任务内,若taskAffinity不相同,则在不同任务中。默认应用程序的taskAffinity值为包名。taskAffinity的值决定了当前Activity 的起始Activity(root Activity)。

Activity的Intent Flag启动模式

Activity的Flag 的比较多,我们讲一下比较常用的:
使用方式:

		Intent i =new Intent(this,StandardActivity.class);
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(i);
  • FLAG_ACTIVITY_NEW_TASK : 启动一个新的Task来启动Activity。
  • FLAG_ACTIVITY_SINGLE_TOP :和给Activity设置SingleTop 效果一致。
  • FLAG_ACTIVITY_CLEAR_TOP :和SingleTask效果一致。
  • FLAG_ACTIVITY_NO_HISTORY :设置这种Flag的Activity将不会在任务栈中保存。
  • LAG_ACTIVITY_EXCLUDE_FROM_RECENTS : 使用这种Flag的Activity的不添加到最近应用列表。和android:excludeFromRecents="true"的效果相同。

Activity 的转场动画的四种实现方式

过渡动画这里讲四种比较简单的过渡动画实现方式。

1. 使用overridePendingTransition方法实现Activity转场动画

使用overridePendingTransition是比较常见的一种实现跳转动画的实现方式,首先我们来看下官方对于这个方法的解释:

/**
     * Call immediately after one of the flavors of {@link #startActivity(Intent)}
     * or {@link #finish} to specify an explicit transition animation to
     * perform next.
     *
     * <p>As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN} an alternative
     * to using this with starting activities is to supply the desired animation
     * information through a {@link ActivityOptions} bundle to
     * {@link #startActivity(Intent, Bundle)} or a related function.  This allows
     * you to specify a custom animation even when starting an activity from
     * outside the context of the current top activity.
     */
    public void overridePendingTransition(int enterAnim, int exitAnim) {
        try {
            ActivityManager.getService().overridePendingTransition(
                    mToken, getPackageName(), enterAnim, exitAnim);
        } catch (RemoteException e) {
        }
    }

简单解释下上面的意思:

  1. overridePendingTransition这个方法需要在startActivity方法或者finish方法之后立即执行才能生效,如果任何延迟执行都将看不到效果,如下代码即看不到动画效果:
mAnimationPendingTopBtn.postDelayed(new Runnable() {
            @Override
            public void run() {
                overridePendingTransition(R.anim.activity_left_to_screen_anim,R.anim.activity_screen_to_right_anim);
            }
        },1);
  1. enterAnim 表示当前Activity进入的动画。
  2. exitAnim 表示前一个Activity 退出的动画。
  3. 如果不需要动画,可以将值赋值为0。

实例

我们做一个简单的从左至右的转场动画:我们从Activity A 跳转至Activity B ,Activity A从屏幕移到屏幕左边退出,Activity B 从屏幕右边移动到屏幕中!简单分析下步骤:

  1. 创建两个动画activity_screen_to_left_anim.xml和activity_right_to_screen_anim.xml
    activity_screen_to_left_anim.xml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="0"
        android:toXDelta="-100%"
        android:duration="500"/>
</set>

activity_right_to_screen_anim.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromYDelta="100%"
        android:toYDelta="0"
        android:duration="500"/>
</set>
  1. 编写overridePendingTransition将编写的动画xml文件应用。
    在startActivity 或者finish后编写overridePendingTransition方法。
overridePendingTransition(R.anim.activity_right_to_screen_anim, R.anim.activity_screen_to_left_anim);

2. 通过定义Theme主题设置转场动画

WindowAnimation 有两种设置方式,一种是通过设置自定义主题Theme,还可以通过 getWindow().setWindowAnimations()方法去实现;在设置之前我们需要自定义动画文件(这里我们用上面创建好的动画文件),然后编辑一个自定义的style。方法如下:

<style name="test_animation" parent="android:Animation.Activity">
         <item name="android:windowEnterAnimation">@anim/activity_bottom_to_screen_anim</item>
        <item name="android:windowExitAnimation">@anim/activity_screen_to_top_anim</item>
         <!--<item name="android:activityOpenEnterAnimation">@anim/activity_top_to_screen_anim</item>-->
        <!--<item name="android:activityOpenExitAnimation">@anim/activity_screen_to_top_anim</item>-->
        <!--<item name="android:activityCloseEnterAnimation">@anim/activity_left_to_screen_anim</item>-->
        <!--<item name="android:activityCloseExitAnimation">@anim/activity_screen_to_right_anim</item>-->
    </style>

简单讲解下属性内容:

  • android:windowEnterAnimation: 新打开Activity的启动动画。
  • android:windowExitAnimation:当前Activity的退出动画。
  • android:activityOpenEnterAnimation:表示即将打开的activity的显示动画
  • android:activityOpenExitAnimation:表示上个Activity的退出动画
  • android:activityCloseEnterAnimation:表示上一个Activity的显示动画
  • android:activityCloseExitAnimation:关闭当前Activity的动画

区别:

  1. 从名字上我们就能看出,window……动画效果作用于整个Window,而activity……只作用域Activity.
  2. window……只能显示即将打开activity的动画,而activity……能显示上一个activity的动画和打开的activity的动画。

定义好了style之后,我们将其设置到Activity上:

第一种:通过设置Theme:

<style name="a_by_theme_animation_theme" mce_bogus="1" parent="AppTheme">
        <item name="android:windowAnimationStyle">@style/test_animation</item>
    </style>

设置Theme到对应的Activity即可。(这里注意,Activity的设置动画只有在Activity新建的时候才会有效果,比如将Activity的启动模式设置为singleInstance,只有第一次启动的时候有动画效果,后面每次跳转都是默认系统动画效果)。

<activity android:name=".aaSource.android.app.Activity.animation.byTheme.AByThemeAnimationActivity"
            android:theme="@style/a_by_theme_animation_theme"
            android:screenOrientation="portrait"
           />

第二种:通过getWindow().setWindowAnimations()方法设置

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         getWindow().setWindowAnimations(R.style.test_animation); 
        setContentView(R.layout.activity_base_animation);
    }

需要注意的是: getWindow().setWindowAnimations()方法 和overridePendingTransition()方法一样,不能做任何延时操作,否则无效果。

3. 使用ActivityOptions切换动画实现Activity转场动画

ActivityOptions是Android 4.1(API 16)才添加的,但是使用时要求API >= 21,所以在使用的过程中需要注意适配问题。ActivityOptions 的使用很简单,我们只需要在启动Activity的时候调用startActivity(Intent intent, @Nullable Bundle options)方法,然后再通过getWindow().setEnterTransition(Transition transition)方法为跳转的Activity 指定特定的动画效果即可。

  1. 在启动Activity 的时候调用startActivity(Intent intent, @Nullable Bundle options)方法。
public static void launch(Activity activity, int type) {
        Intent intent = new Intent(activity, BActivityOptionsActivity.class);
        intent.putExtra(StaticFinalValues.TYPE, type);
        activity.startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(activity).toBundle());
    }
  1. 通过getWindow().setEnterTransition(Transition transition)方法为跳转的Activity 指定特定的动画效果。
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);//特别注意:此方法必须在setContentView之前调用,否则会报错,此方法注释有声明。
        Transition explode = TransitionInflater.from(this).inflateTransition(android.R.transition.explode);
        getWindow().setEnterTransition(explode);
        setContentView(R.layout.activity_base_animation);
    }

注意:getWindow().requestFeature()方法必须在setContentView之前调用,否则会报错。

4. 使用动画共享组件的方式实现跳转Activity转场动画

共享动画属于Transition的一种,同样必须不低于API 21。使用方法如下:

  1. 使用startActivity(Intent intent, @Nullable Bundle options)
public static void launch(Activity activity, View imageView) {
        Intent intent = new Intent(activity, BShareModuleActivity.class);
        activity.startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(activity, imageView, "aserbao_share_name").toBundle());
    }
  1. 在代码中或者xml中给对应的共享组件添加共享名字。
mShowActivityNameTv.setTransitionName("aserbao_share_name");

或者

android:transitionName="aserbao_share_name"

ok,两步搞定。

项目地址

完整项目代码在AserbaosAndroid,如果觉得对你有用,帮忙点个star,谢谢各位。有问题请给我留言,知无不言。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值