zoukankan      html  css  js  c++  java
  • 【转】Android 获取栈最顶层Activity和Application Context解决方案

    在做类似“您的账号在异地登陆,您被迫退出”的dialog弹窗的功能时,不知道怎么获取当前Activity,刚好遇到这篇博主的文章,确实好用,在此记下。
    以前开发都是在别人搭完框架的情况下进行开发,今天遇到一个很头疼的问题,想要在做一个很常见的功能,当接收到极光推送的消息,就在当前页面显示一个dialog通知用户账号在别处已经登录,需要重新登录。这个问题真的是难倒我了,因为极光推送过来的时候,我们并不知道用户操作到了哪一个Activity,而Dialog初始化的时候需要一个Activity或者一个context作为实例化的参数。当我一脸懵逼的时候,还是万能的艳芳姐给我提供了解决的思路。也让我在一定程度上对Application有一定的认知。
    Android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application是单例 (singleton)模式的一个类.且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。因此在安卓中我们可以避免使用静态变量来存储长久保存的值,而用Application。
    这也给我们提供了解决思路,在我们需要获取到当前Context或者Activity对象的时候,我们就可以通过重写这个Application来保存当前的Context或者Activity。

    public class BaseApp extends Application {  
        private static BaseApp mApp;  
        private static Activity sActivity;  
        @Override  
        public void onCreate() {  
            super.onCreate();  
            mApp = this;  
            this.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {  
                @Override  
                public void onActivityCreated(Activity activity, Bundle savedInstanceState) {  
                    Log.d("YWK",activity+"onActivityCreated");  
                }  
    
                @Override  
                public void onActivityStarted(Activity activity) {  
                    Log.d("YWK",activity+"onActivityStarted");  
                    sActivity=activity;  
    
                }  
    
                @Override  
                public void onActivityResumed(Activity activity) {  
    
                }  
    
                @Override  
                public void onActivityPaused(Activity activity) {  
    
                }  
    
                @Override  
                public void onActivityStopped(Activity activity) {  
    
                }  
    
                @Override  
                public void onActivitySaveInstanceState(Activity activity, Bundle outState) {  
    
                }  
    
                @Override  
                public void onActivityDestroyed(Activity activity) {  
    
                }  
            });  
        }  
    
        public static Context getAppContext() {  
            return mApp;  
        }  
    
        public static Resources getAppResources() {  
            return mApp.getResources();  
        }  
    
        public static Activity getActivity(){  
            return sActivity;  
        }  
    }

    这个就是我们重新写的Application,其实我们在做任何项目的时候,应该都会去重写这个Application,去实现一些全局变量的保存,向上面这段代码,我们保存了Activity对象和Context对象,然后重写Application的Oncreate,mApp=this,这里我们保存了一个Application Context,为什么说Application Context呢?我们在下面讨论。
    然后我们通过Application调用registerActivityLifecycleCallbacks的方法,注册一个监听器,对Activity的生命周期进行监听,这样我们只要在一个Activity在start的时候,使sActivity=这个Activity就好了。
    这样在初始化Dialog的时候 AlertDialog.Builder dialog = new AlertDialog.Builder(BaseApp.getActivity());我们将我们Application中获取到的最新的Activity传进去,这样不管用户在哪一个界面,我们都能获取到栈最顶层的Activity。
    最后我们要给我们的应用设置上我们自定义的Application:

    <application  
            android:name=".base.BaseApp"  
            android:allowBackup="true"  
            android:icon="@mipmap/ic_launcher"  
            android:label="@string/app_name"  
            android:supportsRtl="true"  
            android:largeHeap="true"  
    
            android:theme="@style/AppTheme">

    我们通过设置AndroidManifest.xml文件,在application中设置name属性就好了。

    Application Context 和Activity Context的区别:
    为什么我上面说是Application Context而不是说Activity Context呢?在解决上面那个功能的时候,我最开始就在初始化Dialog的时候我是这样写的:
    AlertDialog.Builder dialog = new AlertDialog.Builder(BaseApp.getAppContext());
    结果报错,一直定位在这一行。一直不解,后来才知道Application中获取的Context是一个全局的Application,它和Activity Context的使用场景有很大的不同。


    大家注意看到有一些NO上添加了一些数字,其实这些从能力上来说是YES,但是为什么说是NO呢?下面一个一个解释:
    数字1:启动Activity在这些类中是可以的,但是需要创建一个新的task。一般情况不推荐。
    数字2:在这些类中去layout inflate是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用。
    数字3:在receiver为null时允许,在4.2或以上的版本中,用于获取黏性广播的当前值。(可以无视)
    注:ContentProvider、BroadcastReceiver之所以在上述表格中,是因为在其内部方法中都有一个context用于使用。

    好了,这里我们看下表格,重点看Activity和Application,可以看到,和UI相关的方法基本都不建议或者不可使用Application,并且,前三个操作基本不可能在Application中出现。实际上,只要把握住一点,凡是跟UI相关的,都应该使用Activity做为Context来处理;其他的一些操作,Service,Activity,Application等实例都可以,当然了,注意Context引用的持有,防止内存泄漏。 以上这段话是引用了鸿洋大神的博客,这么一看,我们也就很清楚了Application Context和Activity Context的区别。

    from:http://www.voidcn.com/article/p-ztomovyy-nh.html

    文章乃参考、转载其他博客所得,仅供自己学习作笔记使用!!!
  • 相关阅读:
    swing加载图片
    能有效解决问题的提问方法
    资源在线汇总
    如何赢得别人的尊重
    算法总结
    软件工程概述
    java语言基础汇总
    DEBUG技巧汇总
    web技术发展历程
    java中BufferedImage类的用法
  • 原文地址:https://www.cnblogs.com/xuan52rock/p/14810487.html
Copyright © 2011-2022 走看看