Android ActivityLifecycleCallbacks 分析

      最近产品有个需求就是需要统计前台页面的停留时间,用我们程序员的话来说就是统计Activity在前台的时间,也就是如果程序从启动开始到按home键切换到后台的时候的这段时间内。之前还不知道 ActivityLifecycleCallbacks的时候我就写了一个BaseActivity,然后所有的Activity都去继承该类。但是如果后期项目都已经做好了的话,那在统计的时候就有可能会出现统计不完整的情况,而且最关键的时候有些地方我们使用了Activity,有些地方我们又使用了FragmentActivity这些东西都可能还好的,最坑的是有些地方使用了 PreferenceActivity

ActivityLifecycleCallbacks 使用的好处

    以往我们在监测Activity的生活周期的时候,都会在每个Activity的 onCreate() 或者是 onResume() 中进行写代码去监测,后来我们就写了一个基类BaseActivity去做这些处理,但有些时候还是会遇到一些不方便的问题,这个时候我们在想要能有一个统一的东西去管理该多好。还有就是以后我们在使用统计SDK去统计一些信息的时候也不用每个Activity的生命周期都去写一遍了,比如我们之前在使用友盟SDK的时候,可能会在 onResume() 和 onPause() 方法中都会去写统计的代码,特别的麻烦现在直接可以在接口的实现类中实现就行了。s

用法

  • 要求API 14+ (Android4.0+)
  • 首先需要集成Application,然后在Manifest.xml里面申明自定义Application

    <application
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:name=".NotifyApplication" >
    
    public class NotifyApplication extends Application {
    
        @Override
        public void onCreate() {
            super.onCreate();
            //我们这里可以定义多个的接口监听
            registerActivityLifecycleCallbacks(new ActivityLifecycleOne());
            registerActivityLifecycleCallbacks(new ActivityLifecycleTwo());
            registerActivityLifecycleCallbacks(new ActivityLifecycleThree());
        }
    }
  • 创建一个类去实现 ActivityLifecycleCallbacks并且重写该接口的所有方法,因为我这里会注册多个的监听的,为了测试方便我就抽象出一个基类来,然后其他的ActivityLifecycle都是继承该类

    public abstract class BaseActivityLefecycle implements Application.ActivityLifecycleCallbacks {
    
        private String Tag = getCallbackTag();
    
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            log("onActivityCreated", activity);
        }
    
        @Override
        public void onActivityStarted(Activity activity) {
            log("onActivityStarted", activity);
        }
    
        @Override
        public void onActivityResumed(Activity activity) {
            log("onActivityResumed", activity);
        }
    
        @Override
        public void onActivityPaused(Activity activity) {
            log("onActivityPaused", activity);
        }
    
        @Override
        public void onActivityStopped(Activity activity) {
            log("onActivityStopped", activity);
        }
    
        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
            log("onActivitySaveInstanceState", activity);
        }
    
        @Override
        public void onActivityDestroyed(Activity activity) {
            log("onActivityDestroyed", activity);
        }
    
        public void log(String methodName, Activity activity) {
            Log.i("LOH", methodName + "()..." + 
                                activity.getClass().getSimpleName() + "..." + Tag);
        }
    
        public abstract String getCallbackTag();
    }
    
    public class ActivityLifecycleOne extends BaseActivityLefecycle {
    
        @Override
        public String getCallbackTag() {
            return "ActivityLifecycleOne";
        }
    }
    
    public class ActivityLifecycleTwo extends BaseActivityLefecycle {
    
        @Override
        public String getCallbackTag() {
            return "ActivityLefecycleTwo";
        }
    }
    
    public class ActivityLifecycleThree extends BaseActivityLefecycle {
    
        @Override
        public String getCallbackTag() {
            return "ActivityLifecycleThree";
        }
    }
    
  • 最后我们看看通过 log 打印出来的结果

    I/LOH: onActivityCreated()...MainActivity...ActivityLifecycleOne
    I/LOH: onActivityCreated()...MainActivity...ActivityLefecycleTwo
    I/LOH: onActivityCreated()...MainActivity...ActivityLifecycleThree
    
    I/LOH: onActivityStarted()...MainActivity...ActivityLifecycleOne
    I/LOH: onActivityStarted()...MainActivity...ActivityLefecycleTwo
    I/LOH: onActivityStarted()...MainActivity...ActivityLifecycleThree
    
    I/LOH: onActivityResumed()...MainActivity...ActivityLifecycleOne
    I/LOH: onActivityResumed()...MainActivity...ActivityLefecycleTwo
    I/LOH: onActivityResumed()...MainActivity...ActivityLifecycleThree
    
    I/LOH: onActivityPaused()...MainActivity...ActivityLifecycleOne
    I/LOH: onActivityPaused()...MainActivity...ActivityLefecycleTwo
    I/LOH: onActivityPaused()...MainActivity...ActivityLifecycleThree
    
    ........
    

    在结果的显示中我们看到每个Activity的生命周期,由于我们注册了三个接口回调所以我们就可以看到每个生命周期都是三次的打印,从上面的结果其实我们也能大概的猜测出其内部肯定维持这一个List用于保存我们注册的接口回调的。接下来我们就来看看其内部的实现

实现原理

    首先在Application的内部维持着一个ActivityLifecycleCallbacks的集合变量,当我们调用注册函数的时候,就会将当前的接口回调添加到集合中。其实ActivityLifecycleCallbacks也没有什么神秘的就是一个简单的Application内部接口而已。

private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
            new ArrayList<ActivityLifecycleCallbacks>();

public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
    synchronized (mActivityLifecycleCallbacks) {
        mActivityLifecycleCallbacks.add(callback);
    }
}

//内部接口定义了很多的方法,用于记录Activity的每个生命周期
public interface ActivityLifecycleCallbacks {
    void onActivityCreated(Activity activity, Bundle savedInstanceState);
    void onActivityStarted(Activity activity);
    void onActivityResumed(Activity activity);
    void onActivityPaused(Activity activity);
    void onActivityStopped(Activity activity);
    void onActivitySaveInstanceState(Activity activity, Bundle outState);
    void onActivityDestroyed(Activity activity);
}

      在Android中FragmentActivity, SupportActivity, ActionBarActivity, AppCompatActivity, PreferenceActivity等等都是继承自Activity的,如果我们要统计任何Activity的生命周期的话,那么我们就可以直接在父类Activity中的每个生命周期的方法中进行统计则是最完美的了。下面分别看看Activity中的每个生命周期的方法的一些内容。

  • onCreate生命周期

    protected void onCreate(Bundle savedInstanceState) {
      ......
      getApplication().dispatchActivityCreated(this, savedInstanceState);
    }
  • onStart生命周期

    protected void onStart() {
        ......
        getApplication().dispatchActivityStarted(this);
    }
  • onDestroy生命周期

    protected void onDestroy() {
        ......
    
        getApplication().dispatchActivityDestroyed(this);
    }

    上面只是我们依次的列举了部分的生命周期其实最后都是大同小异的,我们发现不管在哪个生命周期中最后都会指向Application中的一个特定名字的方法中,我们以onCreate生命周期的为例看看Application内部是如何处理的。

//依次遍历接口集合中的接口变量,然后分别调用接口的不同的生命周期函数。
void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) {
    Object[] callbacks = collectActivityLifecycleCallbacks();
    if (callbacks != null) {
        for (int i=0; i<callbacks.length; i++) {
            ((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,
                    savedInstanceState);
        }
    }
}

//这里需要将List集合先转换成一个数组,如果直接操作List的话,会导致在添加和删除集合中的数据的时候会有问题
private Object[] collectActivityLifecycleCallbacks() {
    Object[] callbacks = null;
    synchronized (mActivityLifecycleCallbacks) {
        if (mActivityLifecycleCallbacks.size() > 0) {
            callbacks = mActivityLifecycleCallbacks.toArray();
        }
    }
    return callbacks;
}

    上面代码中我们可以看到首先将List集合转换成一个Array变量,然后依次遍历所有注册的接口,然后分别的调用不同Activity的具体的生命周期的方法。当我们分别的去实现ActivityLifecycleCallbacks接口并且将其子类注册到application中,我们就可以监听任何一个Activity的每个生命周期了。

问题解决

    回到我们最开始的时候如何统计程序的前台停留时间,其实我们只要在自定义的Application中定一个全局的静态变量sCount = 0,如果一个Activity启动的话,则在onActivityStarted方法中sCount++,然后在onActivityStopped()方法中sCount–,最后在onActivityDestroyed的时候判断一下sCount是否等于0表示程序完全退出前台了,还有一种可能就是直接按Home键将程序切换到后台,这个时候你就需要单独的去处理了。其实ActivityLifecycleCallbacks 内部实现是非常简单的,只是在Activity中各个生命周期中调用了接口回调函数,然后Application中定义了接口回调的集合用于保存各个注册的接口。这样子我们定义n多个接口回调,然后分别去分发这些具体的函数。

内容概要:本文档详细介绍了在三台CentOS 7服务器(IP地址分别为192.168.0.157、192.168.0.158和192.168.0.159)上安装和配置Hadoop、Flink及其他大数据组件(如Hive、MySQL、Sqoop、Kafka、Zookeeper、HBase、Spark、Scala)的具体步骤。首先,文档说明了环境准备,包括配置主机名映射、SSH免密登录、JDK安装等。接着,详细描述了Hadoop集群的安装配置,包括SSH免密登录、JDK配置、Hadoop环境变量设置、HDFS和YARN配置文件修改、集群启动与测试。随后,依次介绍了MySQL、Hive、Sqoop、Kafka、Zookeeper、HBase、Spark、Scala和Flink的安装配置过程,包括解压、环境变量配置、配置文件修改、服务启动等关键步骤。最后,文档提供了每个组件的基本测试方法,确保安装成功。 适合人群:具备一定Linux基础和大数据组件基础知识的运维人员、大数据开发工程师以及系统管理员。 使用场景及目标:①为大数据平台建提供详细的安装指南,确保各组件能够顺利安装和配置;②帮助技术人员快速掌握Hadoop、Flink等大数据组件的安装与配置,提升工作效率;③适用于企业级大数据平台的建与维护,确保集群稳定运行。 其他说明:本文档不仅提供了详细的安装步骤,还涵盖了常见的配置项解释和故障排查建议。建议读者在安装过程中仔细阅读每一步骤,并根据实际情况调整配置参数。此外,文档中的命令和配置文件路径均为示例,实际操作时需根据具体环境进行适当修改。
在无线通信领域,天线阵列设计对于信号传播方向和覆盖范围的优化至关重要。本题要求设计一个广播电台的天线布局,形成特定的水平面波瓣图,即在东北方向实现最大辐射强度,在正东到正北的90°范围内辐射衰减最小且无零点;而在其余270°范围内允许出现零点,且正西和西南方向必须为零。为此,设计了一个由4个铅垂铁塔组成的阵列,各铁塔上的电流幅度相等,相位关系可自由调整,几何布置和间距不受限制。设计过程如下: 第一步:构建初级波瓣图 选取南北方向上的两个点源,间距为0.2λ(λ为电磁波波长),形成一个端射阵。通过调整相位差,使正南方向的辐射为零,计算得到初始相位差δ=252°。为了满足西南方向零辐射的要求,整体相位再偏移45°,得到初级波瓣图的表达式为E1=cos(36°cos(φ+45°)+126°)。 第二步:构建次级波瓣图 再选取一个点源位于正北方向,另一个点源位于西南方向,间距为0.4λ。调整相位差使西南方向的辐射为零,计算得到相位差δ=280°。同样整体偏移45°,得到次级波瓣图的表达式为E2=cos(72°cos(φ+45°)+140°)。 最终组合: 将初级波瓣图E1和次级波瓣图E2相乘,得到总阵的波瓣图E=E1×E2=cos(36°cos(φ+45°)+126°)×cos(72°cos(φ+45°)+140°)。通过编程实现计算并绘制波瓣图,可以看到三个阶段的波瓣图分别对应初级波瓣、次级波瓣和总波瓣,最终得到满足广播电台需求的总波瓣图。实验代码使用MATLAB编写,利用polar函数在极坐标下绘制波瓣图,并通过subplot分块显示不同阶段的波瓣图。这种设计方法体现了天线阵列设计的基本原理,即通过调整天线间的相对位置和相位关系,控制电磁波的辐射方向和强度,以满足特定的覆盖需求。这种设计在雷达、卫星通信和移动通信基站等无线通信系统中得到了广泛应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值