小白自我提高学习设计模式笔记—装饰者模式在Android开发的小试

Posted 好人静

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小白自我提高学习设计模式笔记—装饰者模式在Android开发的小试相关的知识,希望对你有一定的参考价值。

前言

        结合着android源码把所有的设计模式总结一下。

        小白自我提高学习设计模式笔记(一)—代理模式

        小白自我提高学习设计模式笔记(二)—装饰者模式

        小白自我提高学习设计模式笔记(三)—装饰者模式在Android开发的小试

        小白自我提高学习设计模式笔记(四)—责任链模式


        在  小白自我提高学习设计模式笔记(二)—装饰者模式中主要总结的是装饰者模式的一些基本理论,了解了装饰者模式主要用来动态给对象添加一些额外的属性或行为,没想到自己在Android项目开发中竟然用了一次装饰者模式,加深了对装饰者模式的认知。

一 需要实现的功能

1.功能描述    

    从Android 4.0以后,Android提供一个比较好用的API:在Application中通过registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback)来实现对Activity的生命周期的监听。

        在项目中通常需要通过监听Activity的生命周期来实现下面几个功能:

 1.通过监听Activity的生命周期来统计应用中打开的未被finish()的Activity,在应用完全退出的时候,将未被关闭的Activity执行finish(),防止在应用退出的时候黑屏显示;

        实现思路:

  •  (1)自定义类来实现ActivityLifecycleCallbacks接口,在实现类维护一个activityManager集合;
  •  (2)在onActivityCreated()中将activity添加到该集合里面,在onActivityDestroyed()中将activity集合中移除
  • (3)最后在APP退出的时候,依次循环该集合中的activity,执行activity.finish()

       具体逻辑见后面的增加了装饰者模式的代码。

 2.通过监听Activity的生命周期来统计该应用中被打开的Activity的个数来判断应用是否处于前后台显示,来实现当APP处于前后台切换的时候增加一些业务逻辑;

        实现思路:

        网上的一些例子是通过activitymamanger.getRunningTasks(1)或activitymanager.getRunningAppProcesss()等方式来判断,这些方法都是基于获取Android系统的正在运行的应用进行判断。

        当然也可以直接通过来统计Activity处于Resume状态的个数来判断APP是否处于前台:

  •   (1)自定义类来实现ActivityLifecycleCallbacks接口,在该实现类中维护一个int类型的变量来统计处于可见状态的Activity的个数;
  • (2)在onActivityStarted()(Activity即将呈现给用户)中对该值进行+1,在onActivityStopped()(Activity已经不可见)中对该值进行-1;
  • (3)由于在一个APP中有且仅有一个Activity会处于前台用户可见,那么在在onActivityStarted()中当该int值等于1的时候,说明应用从后台进入了前台;当在onActivityStopped()中的int值等于0的时候,说明应用有前台进入了后台

         具体逻辑见后面的增加了装饰者模式的代码。

3.通过监听Activity的生命周期来实现应用的埋点功能中的记录前一个页面的字段

        实现思路:

          这里仅仅只提一个埋点中记录当前页面的前一个页面的字段的实现思路。

  • (1)自定义类来实现ActivityLifecycleCallbacks接口,在该类中维护两个字符串分别记录前一个页面和当前页面、一个HashMap记录从onStop状态返回到onResume状态的Activity(因为这里的前一个页面的含义定义为第一次打开该Activity的那个Activity为当前Activity的前一个页面);
  • (2)在onActivityCreated()中分别对两个字符串的值按照对应的逻辑进行赋值;
  • (3)在onActivityStopped()将执行onStop状态的activity添加到HashMap中,如果该Activity是执行的onDestory,那么在onActivityDestoryed将该activity从HashMap中移除

        因为逻辑代码比较多,并不是本次总结的重点,所以不在单独罗列。

  4.等等还有可能需要在ActivityLifecycleCallbacks的实现类中需要实现的功能

2.通常解决方案    

(1)方案一: 全局一个 ActivityLifecycleCallbacks实现类      

        当然可以在整个APP中有一个ActivityLifecycleCallbacks 的实现类,将上面的逻辑都添加在一个类中,当在需要添加一个功能的时候,在该类中在添加代码……

        带来的后果:

        想想这个类的代码有多么可怕,既不符合Java设计模式的 单一原则,如果没有大量的代码注释,也不利于代码的维护。

(2)方案二:每个功能一个ActivityLifecycleCallbacks实现类

        当然在Android中已经考虑了这些因素,在Application中的registerActivityLifecycleCallbacks()和unregisterActivityLifecycleCallbacks()的源码可以看到,在Application中维护的是一个集合,执行register就是往集合中添加一个callback回调,执行unregister就是往集合中删除该callback回调:

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

    public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) 
        synchronized (mActivityLifecycleCallbacks) 
            mActivityLifecycleCallbacks.remove(callback);
        
    

        那么就可以将每个功能来增加一个 ActivityLifecycleCallbacks 的实现类,每添加一个ActivityLifecycleCallbacks的回调的时候,都需要复写下面的几个方法:

   @Override
    public void onActivityCreated(@NonNull @NotNull Activity activity, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) 
    
    @Override
    public void onActivityStarted(@NonNull @NotNull Activity activity) 
    
    @Override
    public void onActivityResumed(@NonNull @NotNull Activity activity) 
    
    @Override
    public void onActivityPaused(@NonNull @NotNull Activity activity) 
    
    @Override
    public void onActivityStopped(@NonNull @NotNull Activity activity) 
    
    @Override
    public void onActivitySaveInstanceState(@NonNull @NotNull Activity activity, @NonNull @NotNull Bundle outState) 
    
    @Override
    public void onActivityDestroyed(@NonNull @NotNull Activity activity) 
    

        带来的后果:

        从1.功能描述    中可以看到每一个功能并不是都需要实现ActivityLifecycleCallbacks的接口方法,如果每增加一个功能都需要实现ActivityLifecycleCallbacks的话,在该实现类中有好几个空方法,并且每增加一个功能,就需要在Application中register和unregister。

3.总结思考

        总结了下现在实现这个功能的特点:

  • (1)需要动态的为Application中的registerActivityLifecycleCallbacks()注册的ActivityLifecycleCallbacks对象添加不同的功能;
  • (2)每个功能只需要实现接口的几个方法就可以完成对应的功能

        感觉和刚刚看的装饰者模式就可以实现这个功能。

二 装饰者模式应用

1.思路整理

        在 小白自我提高学习设计模式笔记(二)—装饰者模式中提到了装饰者模式共有四部分内容Component、ConcreteComponent、Decorator、ConcreteDecorator。每个部分的思路如下:

  • (1)Component:组件。装饰类和被装饰类的父类,用来规范对象的基本功能。

        思路:现在需要实现的功能就是对Activity的生命周期的监听,所以Component就是Application.ActivityLifecycleCallbacks。该部分类似于@link java.io.InputStream。

  • (2)Decorator:装饰类。实现Component接口,持有Component对象,用来为该对象标准化需要添加的功能

        思路:装饰类就是要去实现Application.ActivityLifecycleCallbacks这个接口,然后通过构造函数传入Component对象(即Application.ActivityLifecycleCallbacks对象),然后在装饰类的实现接口方法的时候,通过Component对象来调用对应的接口方法。

        但是我这里其实没有为具体装饰类去抽象需要添加的功能,所以的具体抽象类都是自行实现具体的功能。类似于@link java.io.FilterInputStream的作用。

  • (3)ConcreteDecorator:具体的装饰类。继承或实现Decorator,实现为Component对象动态添加的功能

        思路:具体的装饰类因为都继承了装饰类,所以对于Application.ActivityLifecycleCallbacks(即Component)接口中的方法没有必要必须复写了,只需要按照自己的需要复写对应的生命周期回调方法即可,解决了实现类空方法的问题。类似于@link java.io.BufferedInputStream

  • (4)ConcreteComponent:被装饰类。实现Component接口,实现对象的基本功能。

        思路:这个类在整个设计过程中反复了好几次,首先该类的作用就是为对象的基本功能的定义,像在1.功能描述    中几个功能都不太好定义哪个功能为对象的基本功能,不像其他部分都明确。如果仅仅该类只去实现一个Component接口(即Application.ActivityLifecycleCallbacks接口)显得该类多余,后来就将在1.功能描述    中提到的第二个功能作为了被装饰类,类似于@link java.io.FileInputStream通过构造函数传入name、file等需要处理的文件来对文件进度read操作。

        通过上面的思路整理,如果以后在添加一个功能的时候,只需要在增加一个ConcreteDecorator就可以了。

2.代码实现

        具体的代码实现如下:

  • (1)Component即为Application.ActivityLifecycleCallbacks,不在罗列
  • (2)ConcreteComponent即ApplicationLifecycleCallbacksConcreteComponent类,用来实现监听该应用处于前台还是后台两个状态的转换,代码如下:
public class ApplicationLifecycleCallbacksConcreteComponent implements Application.ActivityLifecycleCallbacks 
    /**
     * 用来监听应用的生命周期,通过该值来判断是否所有的activity都处于onStop状态
     */
    private int foregroundActivityCount;

    /**
     * 生命周期的回调
     *
     * @return
     */
    private IApplicationLifecycle applicationLifecycle;

    public ApplicationLifecycleCallbacksConcreteComponent(IApplicationLifecycle lifecycle) 
        this.applicationLifecycle = lifecycle;
    


    @Override
    public void onActivityCreated(@NonNull @NotNull Activity activity, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) 
    

    @Override
    public void onActivityStarted(@NonNull @NotNull Activity activity) 
        foregroundActivityCount++;
        LogUtils.w("onActivityStarted foregroundActivityCount = " + foregroundActivityCount + " , " + activity.getLocalClassName());
        if (foregroundActivityCount == 1) 
            applicationWillEnterForeground();
        
    

    @Override
    public void onActivityResumed(@NonNull @NotNull Activity activity) 

    

    @Override
    public void onActivityPaused(@NonNull @NotNull Activity activity) 

    

    @Override
    public void onActivityStopped(@NonNull @NotNull Activity activity) 
        foregroundActivityCount--;
        LogUtils.w("onActivityStopped foregroundActivityCount = " + foregroundActivityCount + " , " + activity.getLocalClassName());
        if (foregroundActivityCount == 0) 
            applicationDidEnterBackground();
        
    

    @Override
    public void onActivitySaveInstanceState(@NonNull @NotNull Activity activity, @NonNull @NotNull Bundle outState) 

    

    @Override
    public void onActivityDestroyed(@NonNull @NotNull Activity activity) 

    

    /**
     * 应用后台回调
     */
    private void applicationDidEnterBackground() 
        LogUtils.w("The application did enter background ! ");
        if (applicationLifecycle == null) 
            return;
        
        applicationLifecycle.applicationDidEnterBackground();
    

    /**
     * 应用前台回调
     */
    private void applicationWillEnterForeground() 
        LogUtils.w("The application will enter foreground !");
        if (applicationLifecycle == null) 
            return;
        
        applicationLifecycle.applicationWillEnterForeground();
    

    /**
     * 应用的前后台切换的生命周期
     */
    public interface IApplicationLifecycle 
        /**
         * 应用进入后台
         */

        void applicationDidEnterBackground();

        /**
         * 应用进入到前台
         */
        void applicationWillEnterForeground();
    


  • (3) Decorator即ApplicationLifecycleCallbacksDecorator:持有Component(即Application.ActivityLifecycleCallbacks)对象,并且实现了Component(即Application.ActivityLifecycleCallbacks)接口,代码如下:
public class ApplicationLifecycleCallbacksDecorator implements Application.ActivityLifecycleCallbacks 

    protected Application.ActivityLifecycleCallbacks applicationLifecycleCallbacks;

    public ApplicationLifecycleCallbacksDecorator(Application.ActivityLifecycleCallbacks callbacks) 
        this.applicationLifecycleCallbacks = callbacks;
    

    @Override
    public void onActivityCreated(@NonNull @NotNull Activity activity, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) 
        applicationLifecycleCallbacks.onActivityCreated(activity, savedInstanceState);
    

    @Override
    public void onActivityStarted(@NonNull @NotNull Activity activity) 
        applicationLifecycleCallbacks.onActivityStarted(activity);
    

    @Override
    public void onActivityResumed(@NonNull @NotNull Activity activity) 
        applicationLifecycleCallbacks.onActivityResumed(activity);
    

    @Override
    public void onActivityPaused(@NonNull @NotNull Activity activity) 
        applicationLifecycleCallbacks.onActivityPaused(activity);
    

    @Override
    public void onActivityStopped(@NonNull @NotNull Activity activity) 
        applicationLifecycleCallbacks.onActivityStopped(activity);
    

    @Override
    public void onActivitySaveInstanceState(@NonNull @NotNull Activity activity, @NonNull @NotNull Bundle outState) 
        applicationLifecycleCallbacks.onActivitySaveInstanceState(activity, outState);
    

    @Override
    public void onActivityDestroyed(@NonNull @NotNull Activity activity) 
        applicationLifecycleCallbacks.onActivityDestroyed(activity);
    

  • (4)ConcreteDecorator:继承了Decorator(即ApplicationLifecycleCallbacksDecorator),只选择需要装饰的接口方法进行添加逻辑,代码如下:
public class ActivityManagerOnALCallbacksConcreteDecorator extends ApplicationLifecycleCallbacksDecorator 
    /**
     * 管理Activity的栈
     */
    private List<Activity> activityManager = new ArrayList<>();


    public ActivityManagerOnALCallbacksConcreteDecorator(Application.ActivityLifecycleCallbacks callbacks) 
        super(callbacks);
    


    @Override
    public void onActivityCreated(@NonNull @NotNull Activity activity, Bundle savedInstanceState) 
        super.onActivityCreated(activity, savedInstanceState);
        //保存
        activityManager.add(activity);
    


    @Override
    public void onActivityDestroyed(@NonNull @NotNull Activity activity) 
        super.onActivityDestroyed(activity);
        activityManager.remove(activity);
    
    //....删除不重要无关逻辑

        由于功能3的对应的具体装饰类ActivityLifecycleOnALCallbacksConcreteDecorator也是同样的实现思路,继承装饰类ApplicationLifecycleCallbacksDecorator,复写了需要的方法进行逻辑处理,代码不在单独罗列。

  • (5)装饰者模式的调用:在Application只需要将被装饰对象ConcreteComponent传入具体的装饰类ConcreteDecorator,即可得到该具体装饰类ConcreteDecorator的功能,逻辑的部分代码展示如下:
public class DecoratorApplication extends Application implements ApplicationLifecycleCallbacksConcreteComponent.IApplicationLifecycle 

    @Override
    public void onCreate() 
        super.onCreate();
        registerPharmacyApplicationActivityManager();
        //.....删除不重要逻辑代码
    
 
   private void registerPharmacyApplicationActivityManager() 
        activityManagerOnALCallbacksConcreteDecorator =
                new ActivityManagerOnALCallbacksConcreteDecorator(
                        new ApplicationLifecycleCallbacksConcreteComponent(DecoratorApplication.this));
        registerActivityLifecycleCallbacks(activityManagerOnALCallbacksConcreteDecorator);
    
    //.....删除不重要逻辑代码

        如果以后在有一个需要实现Application.ActivityLifecycleCallbacks的功能,那么只需将增加一个具体的装饰类ConcreteDecorator来继承Decorator(即ApplicationLifecycleCallbacksDecorator),在Application中添加到被装饰类对象即可。也不需要关心Application中的register和unregister以及Application.ActivityLifecycleCallbacks所有的方法复写的问题了。

        相关代码已经上传到github:https://github.com/wenjing-bonnie/pattern.git/的decoratoractivitylifecycle文件夹。

三 总结

        通过一个在Android项目中的实际应用,加深了装饰者模式的设计思想。在代码编写过程中更加深了先要去做思路梳理,在写代码的重要性。其他的设计模式还需要继续学习!加油

以上是关于小白自我提高学习设计模式笔记—装饰者模式在Android开发的小试的主要内容,如果未能解决你的问题,请参考以下文章

小白自我提高学习设计模式笔记—装饰者模式

小白自我提高学习设计模式笔记—模板模式

小白自我提高学习设计模式笔记—模板模式

小白自我提高学习设计模式笔记—模板模式

小白自我提高学习设计模式笔记—装饰者模式在Android开发的小试

小白自我提高学习设计模式笔记—责任链模式