崩溃实例
开发中使用Activity的getApplicationContext()竟然出现空指针崩溃
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.ss.android.article.news/com.bytedance.ugc.message.NotificationListActivity}: java.lang.NullPointerException: Attempt to invoke virtual method ‘android.content.Context android.content.Context.getApplicationContext()’ on a null object
代码实现如下:
class NotificationListActivity : SSMvpSlideBackActivity {
val appContext = this.getApplicationContext()
}
这可真奇怪了!
定位原因
看下getApplicationContext()方法。它被定义在Activity的父类ContextWrapper中,空指针的原因是mBase 为空。
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
而mBase变量来自于ContextWrapper的构造方法
public ContextWrapper(Context base) {
mBase = base;
}
那按理说,mBase不会为空啊。
再看下Activity的创建过程,在Instrumentation类中
public Activity newActivity(Class<?> clazz, Context context,
IBinder token, Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
Object lastNonConfigurationInstance) throws InstantiationException,
IllegalAccessException {
Activity activity = (Activity)clazz.newInstance(); // 1
ActivityThread aThread = null;
// Activity.attach expects a non-null Application Object.
if (application == null) {
application = new Application();
}
activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
info, title, parent, id,
(Activity.NonConfigurationInstances)lastNonConfigurationInstance,
new Configuration(), null /* referrer */, null /* voiceInteractor */,
null /* window */, null /* activityConfigCallback */, null /*assistToken*/); // 2
return activity;
}
可以看到分为两步,
1.通过newInstance来创建activity对象,
2. activity对象与 context和Application绑定。
而例子中的崩溃语句是在 NotificationListActivity类的初始化语句块中,在1处会被执行;此时activity对象中的mBase对象、application对象都为空,就会出现空指针的问题!
修复方法
方法一:
在Application中创建Application的静态实例,在Activity中直接使用Application的静态实例;
方法二:
在初始语句块中声明appContext变量,使用Handler post 初始化或在onCreate()中初始化。