安卓bug - Android中,intent初始化为什么不能写在方法外面呢?

【字号: 日期:2022-10-31浏览:43作者:雯心

问题描述

初学者。今天写一个活动之间跳转的代码,用到了显式的intent,但是我在类中定义了一个intent的成员变量,在方法中使用时候,程序却崩溃了,这是为什么呢?

public class MusicPlay extends Activity{ //下面这一句初始化出了错误 public Intent intent=intent=new Intent(this,MusicServer.class); ....

如上代码,但是错误信息提示是:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method ’java.lang.String android.content.Context.getPackageName()’ on a null object reference

据说是在“空对象引用”上调用getPackageName()虚方法出现了错误。

起初,我以为是不是this是空从而导致问题,修改了代码:

public class MusicPlay extends Activity{ Intent intent; public MusicPlay(){super();if(this!=null){ intent=new Intent(this,MusicServer.class);} } ....

但是仍然出现了错误,错误信息还是一样的。通过条件判断我知道this不为空,那么为什么还说是空引用呢?

问题解答

回答1:

这么做之前, 先要了解清楚Activity与Context之间的关系: 虽然Activity继承了Context, 但是它却不是真正的实现类, 真正的实现可能是ContextWrapper#getBaseContext()返回对象所对应的类.

Activity是ContextWrapper的子类, 所以我们先找到并打开ContextWrapper.java源码, 关键代码如下:

public class ContextWrapper extends Context { public ContextWrapper(Context base) {mBase = base; }/** * Set the base context for this ContextWrapper. All calls will then be * delegated to the base context. Throws * IllegalStateException if a base context has already been set. * * @param base The new base context for this wrapper. */ protected void attachBaseContext(Context base) {if (mBase != null) { throw new IllegalStateException('Base context already set');}mBase = base; }... .../** * @return the base context as set by the constructor or setBaseContext */ public Context getBaseContext() {return mBase; } @Override public AssetManager getAssets() {return mBase.getAssets(); } @Override public Resources getResources() {return mBase.getResources(); } ... ...

ContextWrapper里基于Context的调用都是直接使用mBase来间接实现调用的. 那么这个mBase是什么时候被赋值的呢? 找到并打开ActivityThread.java, 就能找到它被赋值的代码部分, 关键代码如下:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { // System.out.println('##### [' + System.currentTimeMillis() + '] ActivityThread.performLaunchActivity(' + r + ')'); ... ... // ------------------------------------------------------------------- // 创建Activity实例 // ------------------------------------------------------------------- Activity activity = null; try {java.lang.ClassLoader cl = r.packageInfo.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);StrictMode.incrementExpectedActivityCount(activity.getClass());r.intent.setExtrasClassLoader(cl);r.intent.prepareToEnterProcess();if (r.state != null) { r.state.setClassLoader(cl);} } catch (Exception e) {if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException('Unable to instantiate activity ' + component+ ': ' + e.toString(), e);} } try {Application app = r.packageInfo.makeApplication(false, mInstrumentation);if (localLOGV) Slog.v(TAG, 'Performing launch of ' + r);if (localLOGV) Slog.v(TAG, r + ': app=' + app+ ', appName=' + app.getPackageName()+ ', pkg=' + r.packageInfo.getPackageName()+ ', comp=' + r.intent.getComponent().toShortString()+ ', dir=' + r.packageInfo.getAppDir());if (activity != null) { Context appContext = createBaseContextForActivity(r, activity); CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); if (r.overrideConfig != null) {config.updateFrom(r.overrideConfig); } if (DEBUG_CONFIGURATION) Slog.v(TAG, 'Launching activity ' + r.activityInfo.name + ' with config ' + config); Window window = null; if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {window = r.mPendingRemoveWindow;r.mPendingRemoveWindow = null;r.mPendingRemoveWindowManager = null; }// ------------------------------------------------------------------- // 设置 appContext 为Activity 的 BaseContext // ------------------------------------------------------------------- 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);

以上, 可知: 实例化Activity时, ContextWrapper#getBaseContext()返回的是null, 因此, 不能在构造函数或者构造成员变量时直接调用与Context相关的任何函数和类的实例化. 如果需要, 则在其生命周期函数中去调用.

回答2:

你的类继承了Activity类,那么它就有生命周期,所有逻辑都在这几个生命周期里面进行,换而言之,你的逻辑代码都要写在那几个生命周期的方法里面.一般来说,都是重写onCreate的方法,在那里面写页面跳转.你的方法的标识符命名也不规范

回答3:

要重写onCreate()方法啊

相关文章: