为什么在类的开头用findViewById(R.id.******)初始化变量时,我的Android应用程序会出现Nul



这段代码,在顶部注释了块,成功运行:

public class MainActivity extends AppCompatActivity {
    /*
    EditText username = (EditText)findViewById(R.id.editText_Username);
    EditText password = (EditText)findViewById(R.id.editText_Password);
    TextView inputdata = (TextView)findViewById(R.id.textView_InputData);
    TextView welcome = (TextView)findViewById(R.id.textView_Welcome);
    Button login=(Button)findViewById(R.id.button_Login);
    Button anotherLogin=(Button)findViewById(R.id.button_Login_Another);
    */
    public void doLoginOnClick(View v)
    {
        String s1=username.getText().toString();
        inputdata.setText(s1);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab); 
        fab.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    } 
 
}

我正在尝试使用捕获组件的id

findViewById(R.id.***)

正如你所看到的,我把这段代码放在代码开头的注释中。

EditText username = (EditText)findViewById(R.id.editText_Username);
EditText password = (EditText)findViewById(R.id.editText_Password);
TextView inputdata = (TextView)findViewById(R.id.textView_InputData);
TextView welcome = (TextView)findViewById(R.id.textView_Welcome);
Button login=(Button)findViewById(R.id.button_Login);
Button anotherLogin=(Button)findViewById(R.id.button_Login_Another);

如果我删除上面的评论并运行它(在模拟器和真实设备中),程序会立即崩溃,我很惊讶这里出了什么问题?

甚至我也尝试过用构造函数初始化同样的东西。

但如果我把它放在onCreate()里面,就不会崩溃吗?为什么?

我试图获取用户名和密码的信息,并使用将其显示在textView_Inputdata中的文本视图中

EditText username = (EditText)findViewById(R.id.editText_Username);
EditText password = (EditText)findViewById(R.id.editText_Password);
TextView inputdata = (TextView)findViewById(R.id.textView_InputData);
inputdata.setText(username.getText.toString()+" "+password.getText.toString());

有更好或更简单的方法吗?

实例成员变量在初始化实例本身时进行初始化。现在对findViewById() 来说还为时过早

onCreate()之前,您的活动还没有findViewById()内部需要的Window。在setContentView()(您应该在onCreate()中调用)之前,也找不到任何视图。

因此,在onCreate()setContentView()之后初始化视图引用。

添加此代码

 EditText username =  findViewById(R.id.editText_Username);
 EditText password = findViewById(R.id.editText_Password);
 TextView inputdata = findViewById(R.id.textView_InputData);
 TextView welcome = findViewById(R.id.textView_Welcome);
 Button login = findViewById(R.id.button_Login);
 Button anotherLogin = findViewById(R.id.button_Login_Another);

在中

onCreate(); 

后的方法

setContentView(R.layout.activity_main);

嘿,我看到您正在定义和初始化实例变量。我所做的是定义实例变量-EditText username,然后在onCreate方法中初始化它们-username = (EditText) findViewById(R.id.editText_Username);

不初始化实例变量的原因是,元素直到onCreate方法中的setContentView之后才准备好-我可能错了,但我的最佳实践是定义实例变量,然后在onCreate方法

中初始化它们

在设置setContentView()之前,您无法初始化视图项。因为此时将不存在活动的视图。

将初始化保存在一个单独的方法中,并在将视图设置为活动后调用该方法。

您必须在onCreate()中的setContentView()之后调用findViewById(),在此之前没有UI/Layout初始化,这就是为什么您的findViewById()找不到ID并抛出NullPointerException的原因。

public class MainActivity extends AppCompatActivity {
    public void doLoginOnClick(View v){
        String s1 = username . getText ().toString();
        inputdata.setText(s1);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar =(Toolbar) findViewById (R.id.toolbar);
        setSupportActionBar(toolbar);
        EditText username =(EditText) findViewById (R.id.editText_Username);
        EditText password =(EditText) findViewById (R.id.editText_Password);
        TextView inputdata =(TextView) findViewById (R.id.textView_InputData);
        TextView welcome =(TextView) findViewById (R.id.textView_Welcome);
        Button login =(Button) findViewById (R.id.button_Login);
        Button anotherLogin =(Button) findViewById (R.id.button_Login_Another);
        FloatingActionButton fab =(FloatingActionButton) findViewById (R.id.fab);
        fab.setOnClickListener(new View . OnClickListener ()
        {
            @Override
            public void onClick(View view)
            {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
            }
        });
    }
}
  1. 在onCreate()方法之后初始化所有视图

  2. 点击此处阅读有关活动生命周期的更多信息

这样想吧——在告诉活动要使用哪个用户界面布局(xml)之前,它不知道从哪里获取这些视图
您可以执行setContentView(R.layout.your_xml)来告诉活动使用哪个布局作为活动的用户界面。您可以在onCreate回调中执行此操作,因为这是执行"一次性活动级别设置"任务的回调。setContentView()就是这样一个任务。完成此操作后,您可以开始访问布局文件R.layout.your_xml.中的视图

onCreate(...) 
{
    ...
    setContentView(R.layout.your_xml) 
    // Ready to use the views from above xml. 
    findViewById(R.id.your_view) 
    ... 
}

视图绑定将帮助您防止以下问题:

https://developer.android.com/topic/libraries/view-binding

或者在顶部声明视图,并在onCreate()中的setContentView()之后初始化它们。

 public class MainActivity extends AppCompatActivity {
//Declare view on top
EditText username, password;
TextView inputdata,welcome;
Button login,notherLogin;

public void doLoginOnClick(View v)
{
    String s1=username.getText().toString();
    inputdata.setText(s1);
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //set view
    username =  findViewById(R.id.editText_Username);
    password = findViewById(R.id.editText_Password);
    inputdata = findViewById(R.id.textView_InputData);
    welcome = findViewById(R.id.textView_Welcome);
    login = findViewById(R.id.button_Login);
    anotherLogin = findViewById(R.id.button_Login_Another);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab); 
    fab.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View view)
        {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });
} }

setContentView()负责膨胀活动的布局。如果在布局膨胀之前使用任何组件,则它将与NullPointerException一起崩溃。

 @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        setContentView(R.layout.activity_layout);
        username =  findViewById(R.id.editText_Username);
        password = findViewById(R.id.editText_Password);
        inputdata = findViewById(R.id.textView_InputData);
        welcome = findViewById(R.id.textView_Welcome);
        login = findViewById(R.id.button_Login);
        anotherLogin = findViewById(R.id.button_Login_Another);
            
    }

您仍然可以在类的开头声明变量,但必须在onCreate中初始化它。

相关内容

最新更新