简体   繁体   中英

Global View and Local View in Android App

I just wrote a simple Android app with a LinearLayout only. I use this LinearLayout as property of class and as a local object of method (for example in onCreate method).

First case: LinearLayout as a property

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

    LinearLayout root = new LinearLayout(getApplicationContext());

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(root);
    }
}

Second case: LinearLayout as a object of method

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout root = new LinearLayout(getApplicationContext());
        setContentView(root);
    }
}

In both cases, there is no error. However, when I run on simulator or device, the first case ran to error as below. Why? I think this issue is caused by getApplicationContext method. The context of this method hasn't initialized yet until the onCreate method is called. Is this true?

在此处输入图片说明

E/AndroidRuntime: FATAL EXCEPTION: main Process: localglobal, PID: 6701 java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{localglobal/localglobal.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2209) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) at android.app.ActivityThread.access$800(ActivityThread.java:144) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) at com.andro id.internal.os.ZygoteInit.main(ZygoteInit.java:694) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:105) at localglobal.MainActivity.(MainActivity.java:9) at java.lang.reflect.Constructor.newInstance(Native Method) at java.lang.Class.newInstance(Class.java:1572) at android.app.Instrumentation.newActivity(Instrumentation.java:1065) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2199) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) at android.app.ActivityThread.access$800(ActivityThread.java:144) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

When a Context object is first initialized, it isn't ready to be used as a Context yet, and most of its methods will return null . The Activity class is an extension of the Context class, so it follows the same rules.

When you have:

LinearLayout root = new LinearLayout(getApplicationContext());

as a global variable, Java will attempt to initialize your LinearLayout while your MainActivity is initializing, before the Context has been attached or prepared. getApplicationContext() is likely returning null , although even passing this would cause errors, since Views use the Context during initialization to call getResources() , which will also be null at that point.

That's why Android provides the onCreate() method. This method is only called once the Context has been attached and is ready for use.

If you want a global LinearLayout variable, do this:

public class MainActivity extends AppCompatActivity {
    private LinearLayout root;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        root = new LinearLayout(this);
        setContentView(root);
    }
}

However, this isn't the way Android is meant to really work. Instead, you should create a layout XML (under /res/layouts/ , Android Studio should have done this for you anyway), where you define your layout in XML, and give your Views ids. Then in your Activity:

public class MainActivity extends AppCompatActivity {
    private LinearLayout root;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.your_layout_name);
        root = findViewById(R.id.whatever_id_you_gave_your_linearlayout_in_xml);
    }
}

Your layout XML might look something like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/whatever_id_you_gave_your_linearlayout_in_xml"
    android:orientation="vertical">

    <TextView
        android:id="@+id/some_other_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
     />

     <Button
        android:id="@+id/a_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
     />

</LinearLayout>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM