【转】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

posted on 2021-05-25 20:49  神奇的旋风  阅读(1630)  评论(0编辑  收藏  举报

导航