窗体泄露(二)

窗体泄露(二)

日志

Bad window token, you cannot show a dialog before an Activity is created or after it's hidden.

分析

窗体泄露。Application获Context是一全局Application,不同于Activity、Context使用场景。详参。

解决

package application;

...

/**
 * Created on 2017/8/22.
 *
 * @author xxx
 * @desc 官方文档
 * Base class for those who need to maintain global application state.
 * You can provide your own implementation by specifying its name in your AndroidManifest.xml's <application> tag,
 * which will cause that class to be instantiated for you when the process for your application/package is created.
 * Application类(基础类)用于维护应用程序全局状态。
 * 你可提供自己的实现,在AndroidManifest.xml文件<application>标签指定它的名字,
 * 这将引起你的应用进程被创建时Application类为你被实例化。
 * <p>
 * Android系统在每应用程序运行时创且仅创一Application实例,故Application可当单例(Singleton)模式一类;
 * 对象生命周期整应用程序最长,等同应用程序生命周期;
 * 全局唯一,不同Activity、Service中获实例相同;
 * 数据传递、数据共享、数据缓存等。
 */
public class App extends LitePalApplication {  
    private Activity currentActivity;
  
    public static App getInstance() {
        return instance;
    }

    /**
     * 应用程序创调
     * 创和实例化任何应用程序状态变量或共享资源变量,方法内获Application单例。
     */
    @Override
    public void onCreate() {
        LogManager.e("Application", "onCreate");
        super.onCreate();     
        // Application本已单例(可如下处理)
        instance = this;
        // 初始化配置
        initConfiguration();
    }

    /**
     * 应用程序对象终止调
     * 不定调。当应用程序被内核终止为别应用程序释放资源,将不提醒且不调用应用程序对象onTerminate()而直接终止进程。
     */
    @Override
    public void onTerminate() {
        LogManager.e("Application", "onTerminate");
        super.onTerminate();
    }

    /**
     * 系统资源匮乏调
     * 通在后台进程已结束且前台应用程序仍缺内存时调,重写该方法清空缓存或释放非必要资源。
     */
    @Override
    public void onLowMemory() {
        LogManager.e("Application", "onLowMemory");
        super.onLowMemory();
    }

    /**
     * 运行时决定当前应用程序应减内存开销时(通常进入后台运行)调,含一level参数,用于提供请求的上下文。
     *
     * @param level 级别
     */
    @Override
    public void onTrimMemory(int level) {
        LogManager.e("Application", "onTrimMemory");
        super.onTrimMemory(level);
    }

    /**
     * 与Activity不同,配置改变时应用程序对象不终止和重启。若应用程序用值依赖特定配置,则重写该方法加载这些值或于应用程序级处理配置值改变。
     *
     * @param newConfig 配置
     */
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        LogManager.e("Application", "onConfigurationChanged");
        super.onConfigurationChanged(newConfig);
    }

    /**
     * 初始化配置
     */
    private void initConfiguration() {
        // 全局监听Activity生命周期
        registerActivityListener();       
    }

    /**
     * Activity全局监听
     */
    private void registerActivityListener() {
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                currentActivity = activity;
            }

            @Override
            public void onActivityStarted(Activity 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) {
                // 将监听到销事件Activity移除集合
                ActivitySuperviseUtils.finishActivity(activity);
            }
        });
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(base);
    }
    
    public Activity getCurrentActivity() {
        return currentActivity;
    }
}