Android bug - In Android, why can't intent initialization be written outside the method?
伊谢尔伦
伊谢尔伦 2017-05-16 13:35:09
0
3
911

beginner. Today I wrote a code to jump between activities, using an explicit intent, but I defined an intent member variable in the class, and when I used it in the method, the program crashed. Why is this?

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

The code is as above, but the error message is:

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

It is said that an error occurred when calling the getPackageName() virtual method on "null object reference".

At first, I thought that this was empty and caused the problem, so I modified the code:


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

But an error still occurs and the error message is still the same. Through conditional judgment, I know that this is not empty, so why is it still said to be a null reference?

伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

reply all(3)
phpcn_u1582

Before doing this, you must first understand ActivityContext之间的关系: 虽然Activity继承了Context, 但是它却不是真正的实现类, 真正的实现可能是ContextWrapper#getBaseContext()the class corresponding to the returned object.

ActivityContextWrapper的子类, 所以我们先找到并打开ContextWrapper.javaSource code, the key code is as follows:

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, you can find the code part where it is assigned. The key code is as follows:

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);

From the above, it can be seen that: Instantiate any functions and classes related to Activity时, ContextWrapper#getBaseContext()返回的是null, 因此, 不能在构造函数或者构造成员变量时直接调用与Context. If necessary, call it in its life cycle function.

伊谢尔伦

Your class inherits the Activity class, then it has a life cycle, and all logic is carried out in these life cycles. In other words, your logic code must be written in the methods of those life cycles. Generally speaking, you override the onCreate method and write page jumps there. The identifier naming of your method is also not standardized

Peter_Zhu

You need to override the onCreate() method

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template