英文:
Importing int variable from another class crashes app
问题
<br>
我正在尝试设计一个乘法口诀测试应用程序,理论是用户会看到一个屏幕,上面有12个按钮可以选择。 <br>当他按下一个按钮时,它会打开一个新的类,用他选择的数字来进行测试。 <br>有4个主要的文件:
MainActivity.java
activity_main.xml
Times.java
activity_times.java
<br>当前用于测试用户的类视图(activity_times.xml
)只包含三个文本视图:
"HI" id=textView
""(空白,将在Java类中编辑)id=TextOut
"正在开发中...." id=textView2
第一个和最后一个文本视图并不重要,稍后会将它们移除。
<br>在MainActivity.java
类中,我声明了一个共享变量
public int numberClicked;
然后告诉按钮将该变量设置为某个数字:
button2 = findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 2;
openTestPage();
}
});
然后在Times.java
类中,我告诉它导入这个变量和空输出文本视图:
private MainActivity MA;
private int SubjectNumber = MA.numberClicked;
private final TextView OutputText = findViewById(R.id.TextOut);
然后将文本视图设置为导入的变量:
OutputText.setText("您选择了数字 " + SubjectNumber);
我想要的输出是在屏幕上,TextOut
文本视图显示,例如如果用户按下上面有数字“2”的按钮:“您选择了数字2”。
<br>
但是,实际上,当第二个类视图启动时,应用程序会崩溃
<br>为了阻止它崩溃,我必须注释掉以下代码:
private MainActivity MA;
private int SubjectNumber = MA.numberClicked;
private final TextView OutputText = findViewById(R.id.TextOut);
如果只取消注释三行中的一行,它仍然会崩溃。
我查看了日志,发现了一些有趣的信息:
2020-08-23 15:20:18.553 6537-6537/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.ma, PID: 6537
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.ma/com.example.ma.Times}: java.lang.NullPointerException: Attempt to read from field 'int com.example.ma.MainActivity.numberClicked' on a null object reference
...
完整的日志内容可以在 此处 找到。
我的 AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ma">
<application
...
</application>
</manifest>
我的 MainActivity.java
:
package com.example.ma;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
public int numberClicked;
private Button button2;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
}
public void openTestPage() {
Intent intent = new Intent(this, Times.class);
startActivity(intent);
}
}
我的 activity_main.xml
:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
<TextView
android:id="@+id/Instructions"
...
</TextView>
...
</androidx.constraintlayout.widget.ConstraintLayout>
我的 Times.java
:
package com.example.ma;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class Times extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_times);
TextView OutputText = findViewById(R.id.TextOut);
int SubjectNumber = getIntent().getIntExtra("numberClicked", 0);
OutputText.setText("您选择了数字 " + SubjectNumber);
}
}
我的 activity_times.xml
:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
<TextView
android:id="@+id/textView2"
...
/>
<TextView
android:id="@+id/textView"
...
/>
<TextView
android:id="@+id/TextOut"
...
/>
</androidx.constraintlayout.widget.ConstraintLayout>
英文:
<br>
I'm trying to design a times table testing app, the theory is that the user is presented with a screen with 12 buttons to select from.
<br>When he presses a button it opens a new class testing him with the number he chose. <br> There are 4 main files:
MainActivity.java
activity_main.xml
Times.java
activity_times.java
<br>Currently the class view that comes up to test the user (activity_times.xml
), just contains three text views:
"HI" id=textView
"" (empty to be edited in the java class) id=TextOut
"Under development...." id=textView2
The first and last text views are not important, they'll be removed later on.
<br>In the MainActivity.java
class I declared a shared variable
public int numberClicked;
and then told the buttons to set the variable to a certain number:
button2 = findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 2;
openTestPage();
}
});
and then on the Times.java
class I told it to import it and the empty output text view:
private MainActivity MA;
private int SubjectNumber = MA.numberClicked;
private final TextView OutputText = findViewById(R.id.TextOut);
and then to set the text view to the imported variable:
OutputText.setText("You chose the number " + SubjectNumber);
The output I want is that on the screen is that the TextOut
text view shows, for example if the user presses the button with the number "2" on it: "You chose the number 2".
<br>
But instead of that, the app crashes when the second class view launches
<br> To stop it from crashing I have to comment out the following code:
private MainActivity MA;
private int SubjectNumber = MA.numberClicked;
private final TextView OutputText = findViewById(R.id.TextOut);
If I uncomment only one of the three lines it will still crash.
I looked in the logcat and saw something interesting:
2020-08-23 15:20:18.553 6537-6537/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.ma, PID: 6537
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.ma/com.example.ma.Times}: java.lang.NullPointerException: Attempt to read from field 'int com.example.ma.MainActivity.numberClicked' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2844)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3049)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1809)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6680)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.NullPointerException: Attempt to read from field 'int com.example.ma.MainActivity.numberClicked' on a null object reference
at com.example.ma.Times.<init>**(Times.java:13)**
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:41)
at android.app.Instrumentation.newActivity(Instrumentation.java:1215)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2832)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3049) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1809) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:193) 
at android.app.ActivityThread.main(ActivityThread.java:6680) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
Every thing that came out of the logcat you will find here.
My AndroidManefest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ma">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="Times Practice"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".Times">
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts" />
</application>
</manifest>
My MainActivity.java
package com.example.ma;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
public int numberClicked;
private Button button2;
private Button button3;
private Button button4;
private Button button5;
private Button button6;
private Button button7;
private Button button8;
private Button button9;
private Button button10;
private Button button11;
private Button button12;
private Button button13;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button2 = findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 2;
openTestPage();
}
});
button3 = findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 3;
openTestPage();
}
});
button4 = findViewById(R.id.button4);
button4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 4;
openTestPage();
}
});
button5 = findViewById(R.id.button5);
button5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 5;
openTestPage();
}
});
button6 = findViewById(R.id.button6);
button6.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 6;
openTestPage();
}
});
button7 = findViewById(R.id.button7);
button7.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 7;
openTestPage();
}
});
button8 = findViewById(R.id.button8);
button8.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 8;
openTestPage();
}
});
button9 = findViewById(R.id.button9);
button9.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 9;
openTestPage();
}
});
button10 = findViewById(R.id.button10);
button10.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 10;
openTestPage();
}
});
button11 = findViewById(R.id.button11);
button11.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 11;
openTestPage();
}
});
button12 = findViewById(R.id.button12);
button12.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 12;
openTestPage();
}
});
button13 = findViewById(R.id.button13);
button13.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
numberClicked = 13;
openTestPage();
}
});
}
public void openTestPage() {
Intent intent = new Intent(this, Times.class);
startActivity(intent);
}
}
My activity_main.xml
:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<TextView
android:id="@+id/Instructions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/acme"
android:gravity="center"
android:text="Choose the number you want to practice your times tables with....."
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="36sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.051" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/architects_daughter"
android:text="2"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/button5"
app:layout_constraintEnd_toStartOf="@+id/button3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/Instructions" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/architects_daughter"
android:text="3"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/button6"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/Instructions" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/architects_daughter"
android:text="4"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/button7"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.493"
app:layout_constraintStart_toEndOf="@+id/button3"
app:layout_constraintTop_toBottomOf="@+id/Instructions" />
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/architects_daughter"
android:text="5"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/button6"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.499" />
<Button
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/architects_daughter"
android:text="6"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.499" />
<Button
android:id="@+id/button7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/architects_daughter"
android:text="7"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.493"
app:layout_constraintStart_toEndOf="@+id/button6"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/architects_daughter"
android:text="8"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/button11"
app:layout_constraintEnd_toStartOf="@+id/button9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button5" />
<Button
android:id="@+id/button9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/architects_daughter"
android:text="9"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/button12"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button6" />
<Button
android:id="@+id/button10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/architects_daughter"
android:text="10"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/button13"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/button9"
app:layout_constraintTop_toBottomOf="@+id/button7" />
<Button
android:id="@+id/button11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="80dp"
android:fontFamily="@font/architects_daughter"
android:text="11"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/button12"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/button12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="80dp"
android:fontFamily="@font/architects_daughter"
android:text="12"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/button13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="80dp"
android:fontFamily="@font/architects_daughter"
android:text="13"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/button12" />
</androidx.constraintlayout.widget.ConstraintLayout>
My Times.java
:
package com.example.ma;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class Times extends AppCompatActivity {
private MainActivity MA;
private int SubjectNumber = MA.numberClicked;
private final TextView OutputText = findViewById(R.id.TextOut);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_times);
OutputText.setText("You chose the number " + SubjectNumber);
}
}
My activity_times.xml
:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".Times">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Under development...."
android:textSize="28sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.503"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.696" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HI"
android:textSize="100sp"
app:layout_constraintBottom_toTopOf="@+id/TextOut"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/TextOut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="316dp"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
答案1
得分: 1
你不能直接将数据从一个活动传递到另一个活动,你只需要通过意图(intent)或捆绑(bundle)来传递。这里我正在更新你的代码。
MainActivity.java
public void openTestPage(int numberClicked) {
Intent intent = new Intent(this, Times.class);
intent.putExtra("intVariableName", numberClicked);
startActivity(intent);
}
Times.java
Intent intent = getIntent();
int intValue = intent.getIntExtra("intVariableName", 0);
OutputText.setText("你选择了数字 " + intValue);
请注意,我已经将 HTML 编码转换为普通文本,以便更好地阅读。
英文:
You can't directly pass the data from one activity to another you just need to pass through intent or bundle. Here I am updating your code.
MainActivity.java
public void openTestPage(int numberClicked) {
Intent intent = new Intent(this, Times.class);
intent.putExtra("intVariableName", numberClicked);
startActivity(intent);
}
Times.java
Intent intent = getIntent();
int intValue = intent.getIntExtra("intVariableName", 0);
OutputText.setText("You chose the number " + intValue);
答案2
得分: 1
你不应该尝试直接从一个Activity访问另一个Activity。在Android中,你可以将想要与另一个Activity共享的数据添加到一个Intent中。你也不应该在Activity的生命周期之外获取视图。你的 findViewById()
应该移动到Activity的 onCreate()
方法中。
在你的第一个Activity的 openTestPage()
方法中:
Intent intent = new Intent(this, Times.class);
// 将想要传递给另一个Activity的值添加到Intent中
intent.putExtra("NUMBER_CLICKED", numberClicked);
startActivity(intent);
你的第二个Activity应该类似于以下代码:
public class Times extends AppCompatActivity {
private int SubjectNumber;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_times);
// 在这里访问你的视图
TextView OutputText = findViewById(R.id.TextOut);
// 检索传递到Intent中的值
// (0是一个默认值,可以替换为其他值。)
SubjectNumber = getIntent().getIntExtra("NUMBER_CLICKED", 0);
OutputText.setText("你选择了数字 " + SubjectNumber);
}
}
英文:
You shouldn't try to directly access an Activity from another Activity. In Android, you add the data you want to share with another Activity onto an Intent. You also shouldn't try to obtain a view outside of the Activity lifecycle. Your findViewById()
should be moved to the Activity's onCreate()
.
In your first Activity's openTestPage()
:
Intent intent = new Intent(this, Times.class);
// Add the value you want to pass to the other Activity
// to the Intent
intent.putExtra("NUMBER_CLICKED", numberClicked);
startActivity(intent);
Your second Activity should look something like this:
public class Times extends AppCompatActivity {
private int SubjectNumber;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_times);
// Access your views here
TextView OutputText = findViewById(R.id.TextOut);
// Retrieve the value passed into the Intent
// (The 0 is a default value to fallback on. You can use another value.)
SubjectNumber = getIntent().getIntExtra("NUMBER_CLICKED", 0);
OutputText.setText("You chose the number " + SubjectNumber);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论