Caused by: java.lang.IllegalStateException: System services not available to Activities before onCre
刚刚写垂重跑马灯demo的时候,被报了一个 System services not available to Activities before onCreate()
错误
错误日志如下:
05-18 17:13:24.634 1598-1598/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.verticalmarquee.maomao.verticalmarqueedemo, PID: 1598
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.verticalmarquee.maomao.verticalmarqueedemo/com.verticalmarquee.maomao.verticalmarqueedemo.MainActivity}: java.lang.IllegalStateException: System services not available to Activities before onCreate()
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2354)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2503)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1353)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5529)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:635)
Caused by: java.lang.IllegalStateException: System services not available to Activities before onCreate()
at android.app.Activity.getSystemService(Activity.java:5293)
at android.view.LayoutInflater.from(LayoutInflater.java:229)
at com.verticalmarquee.maomao.verticalmarqueedemo.MainActivity.<init>(MainActivity.java:15)
at java.lang.Class.newInstance(Native Method)
at android.app.Instrumentation.newActivity(Instrumentation.java:1067)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2344)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2503)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1353)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5529)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:635)
我以为是自己在onCreate里面启动跑马灯动画的原因,但细想一下,不对啊,动画至少延时2秒之后执行,一个小demo,不至于启动这么慢吧?
最后发现我做了一个偷懒的操作。
因为跑马灯需要inflate很多个View,所以我将初始化LayoutInflater的操作放在了Activity的属性里面。
public class MainActivity extends AppCompatActivity {
private VerticalMarqueeLayout marqueeRoot;
private LayoutInflater mInflater = LayoutInflater.from(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
}
}
为什么作为属性就会导致应用挂掉了呢?
原因分析:
通过错误日志的堆栈信息顺藤摸瓜找到了Activity启动的位置。
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
...
final Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
if (!r.activity.mFinished && pendingActions != null) {
pendingActions.setOldState(r.state);
pendingActions.setRestoreInstanceState(true);
pendingActions.setCallOnPostCreate(true);
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
return a;
}
跟进去看performLaunchActivity(r, customIntent);的代码,发现activity实例化之后调用了activity.attach()方法。
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
} catch (Exception e) {
...
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
...
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
...
r.activity = activity;
}
r.setState(ON_CREATE);
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
我的报错位置就是在Activity实例化的时候。我们再看看LayoutInflater.from(this);里面的源码发现:它是通过Context获取到一个layout_inflater的Service。
public static LayoutInflater from(Context context) {
LayoutInflater LayoutInflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (LayoutInflater == null) {
throw new AssertionError("LayoutInflater not found.");
}
return LayoutInflater;
}
然而Activity的Context是在attach方法里面才绑定,在实例化Activity的过程中,Activity里面不包含可用的Context。
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback) {
attachBaseContext(context);
}
总结:
Activity初始化之后,如果activity不为null,回调用activity.attach(...)方法,attach方法里面的attachBaseContext(context)方法会将context实例与activity实例绑定在一起。
问题原因:
由于我在Activity初始化的时候写了LayoutInflater.from(this);而执行LayoutInflater.from(this);代码的时候传入的Context是不可用的。最后在查找Service的时候抛出了异常。
得到的教训:
- 不是所有省空间的做法都是对的,不能打破原有的规律;
- 源码要常翻翻,了解了原理才能更好的掌控代码;
(标签:Activity、LayoutInflater、Context)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- springboot 默认日志配置源码
- logback 通过javaconfig实现配置
- springboot通过javaconfig实现logback配置
- 干货来了,vue 3.0 自定义指令变化
- XXE注入漏洞
- vue + typescript 类组件教程
- 图像处理笔记(3)----OpenCV图像算术运算
- V - Distpicker 是一个简单易用的地区选择器
- [漫谈] 状态
- 变量覆盖
- 【Rust日报】2020-08-27 在Arduino Uno上面跑 Rust 程序
- 浅谈类加载
- Rust FFI 编程 - Rust导出共享库06
- go语言文件操作汇总
- Redis 主从复制 哨兵模式实战