Calling startActivity() from outside of an Activity context requires the FLAG_..

1,147 阅读2分钟

一、错误描述

Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

二、错误跟踪

项目中涉及到Activity之间相互跳转的代码封装一下,代码如下:

/**
 * 启动新的Activity
 * @param context 当前Activity
 * @param cls     要启动的Activity的类
 */
public static void startActivityUtils(Context context , Class cls){
    Intent intent = new Intent();
    intent.setClass(context, cls);
    context.startActivity(intent);
}

三、错误分析

Context中有一个startActivity方法,Activity继承自Context,重写了startActivity方法。如果使用Activity的startActivity方法,不会有任何限制,而如果使用Context的startActivity方法的話,就需要开启一个新的的task,遇到这个异常,是因为使用了Context的startActivity方法。

四、解决办法

解决办法是,加一个flag。 代码:intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK ); 这样就可以在新的task里面启动这个Activity了。

    /**
    * 启动新的Activity
    * @param context 当前Activity
    * @param cls     要启动的Activity的类
    */
 public static void startActivityUtils(Context context , Class cls){
     Intent intent = new Intent();
     intent.setClass(context, cls);
     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
     context.startActivity(intent);
}

五、关于Context和Activity的知识点

  • Context与Activity有什么关系?
  • Context对于Activity有什么作用?
  • 不同类型的Context的应用场景是什么?

(一)Context与 ctivity 有什么关系?

Context是一个抽象类;Activity继承了Context。具体继承关系如下:

Context的直接实现子类:ContextImp、ContextWrapper;

ContextWrapper的子类是常用的Activity、Service、Application;

为什么Activity通过ContextThemeWrapper间接继承ContextWrapper,而Service跟Application直接继承ContextWrapper呢?

答:ContextThemeWrapper类包含了与主题Theme相关的接口,而只有Activity才需要主题,Service跟Application不需要。以下是ContextThemeWrapper的源码

(二)Context对于Activity有什么作用?

Activity 通过 Context接口 去访问Android系统的服务 & 资源,主要包括:

  • 获取应用相关信息
  • 获取系统/应用资源
  • 四大组件之间的交互
  • 文件相关
  • 数据库相关

(三)不同类型的Context的应用场景是什么?

最终的Context类型主要包括:Activity、Service & Application,那么使用这三者的应用场景区别是什么呢

1、与UI相关的场景,都使用Activity类型Context

因为是针对当前UI界面资源进行操作 & 继承自ContextThemeWrapper(可自定义主题样式),如show a dialog、 Layout Inflation等。Activity.this返回的是当前Activity的Context

2、生命周期较长的对象,都使用Application类型Context

因为Application Context的生命周期与应用保持一致,可避免出现Context引用的内存泄漏 。getApplication()与getApplicationContext()返回的是同一个Applicatoin对象,但作用域不同:getApplicatoin()的作用域:Activity、Service,但不能在BroadcastReceiver里使用; getApplicationContext()的作用域会广一些,如包括BroadcastReceiver等。