Java Android计算器应用程序运行时立即崩溃
我正在为我在学校的课堂项目开发一个计算器应用程序,但在幕后似乎有一些不基于语法的错误。我试图运行我的应用程序,但它崩溃了。我一直无法找到我的错误,但它总是崩溃后,我点击提交按钮。我还没有完全拒绝运行的应用程序 AndroidManifest.xmlJava Android计算器应用程序运行时立即崩溃,java,android,xml,calculator,Java,Android,Xml,Calculator,我正在为我在学校的课堂项目开发一个计算器应用程序,但在幕后似乎有一些不基于语法的错误。我试图运行我的应用程序,但它崩溃了。我一直无法找到我的错误,但它总是崩溃后,我点击提交按钮。我还没有完全拒绝运行的应用程序 AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" pa
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.stins.calculator">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name="com.example.stins.calculator.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
CalcImpl.java
package com.example.stins.calculator;
public class CalculatorImpl {
private String mDisplayedValue;
private String mDisplayedFormula;
private String mLastKey;
private String mLastOperation;
private Calculator mCallback;
private boolean mIsFirstOperation;
private boolean mResetValue;
private double mBaseValue;
private double mSecondValue;
public CalculatorImpl(Calculator calculator) {
mCallback = calculator;
resetValues();
setValue("0");
setFormula("");
}
public CalculatorImpl(Calculator calculatorInterface, String value) {
mCallback = calculatorInterface;
resetValues();
mDisplayedValue = value;
setFormula("");
}
private void resetValueIfNeeded() {
if (mResetValue) mDisplayedValue = "0";
mResetValue = false;
}
private void resetValues() {
mBaseValue = 0;
mSecondValue = 0;
mResetValue = false;
mLastKey = "";
mLastOperation = "";
mDisplayedValue = "";
mDisplayedFormula = "";
mIsFirstOperation = true;
}
public void setValue(String value) {
mCallback.setValue(value);
mDisplayedValue = value;
}
private void setFormula(String value) {
mCallback.setFormula(value);
mDisplayedFormula = value;
}
private void updateFormula() {
final String first = Formatter.doubleToString(mBaseValue);
final String second = Formatter.doubleToString(mSecondValue);
final String sign = getSign(mLastOperation);
if (sign.equals("√")) {
setFormula(sign + first);
} else if (!sign.isEmpty()) {
setFormula(first + sign + second);
}
}
public void setLastKey(String mLastKey) {
this.mLastKey = mLastKey;
}
public void addDigit(int number) {
final String currentValue = getDisplayedNumber();
final String newValue = formatString(currentValue + number);
setValue(newValue);
}
private String formatString(String str) {
// if the number contains a decimal, do not try removing the leading zero anymore, nor add group separator
// it would prevent writing values like 1.02
if (str.contains(".")) return str;
final double doubleValue = Formatter.stringToDouble(str);
return Formatter.doubleToString(doubleValue);
}
private void updateResult(double value) {
setValue(Formatter.doubleToString(value));
mBaseValue = value;
}
public String getDisplayedNumber() {
return mDisplayedValue;
}
public double getDisplayedNumberAsDouble() {
return Formatter.stringToDouble(getDisplayedNumber());
}
public String getDisplayedFormula() {
return mDisplayedFormula;
}
public void handleResult() {
mSecondValue = getDisplayedNumberAsDouble();
calculateResult();
mBaseValue = getDisplayedNumberAsDouble();
}
public void calculateResult() {
if (!mIsFirstOperation) updateFormula();
switch (mLastOperation) {
case Constants.PLUS:
updateResult(mBaseValue + mSecondValue);
break;
case Constants.MINUS:
updateResult(mBaseValue - mSecondValue);
break;
case Constants.MULTIPLY:
updateResult(mBaseValue * mSecondValue);
break;
case Constants.DIVIDE:
divideNumbers();
break;
case Constants.MODULO:
moduloNumbers();
break;
case Constants.POWER:
powerNumbers();
break;
case Constants.ROOT:
updateResult(Math.sqrt(mBaseValue));
break;
default:
break;
}
mIsFirstOperation = false;
}
private void divideNumbers() {
double resultValue = 0;
if (mSecondValue != 0) resultValue = mBaseValue / mSecondValue;
updateResult(resultValue);
}
private void moduloNumbers() {
double resultValue = 0;
if (mSecondValue != 0) resultValue = mBaseValue % mSecondValue;
updateResult(resultValue);
}
private void powerNumbers() {
double resultValue = Math.pow(mBaseValue, mSecondValue);
if (Double.isInfinite(resultValue) || Double.isNaN(resultValue)) resultValue = 0;
updateResult(resultValue);
}
public void handleOperation(String operation) {
if (mLastKey.equals(Constants.DIGIT)) handleResult();
mResetValue = true;
mLastKey = operation;
mLastOperation = operation;
if (operation.equals(Constants.ROOT)) calculateResult();
}
public void handleClear() {
final String oldValue = getDisplayedNumber();
String newValue = "0";
final int len = oldValue.length();
int minLen = 1;
if (oldValue.contains("-")) minLen++;
if (len > minLen) newValue = oldValue.substring(0, len - 1);
newValue = newValue.replaceAll("\\.$", "");
newValue = formatString(newValue);
setValue(newValue);
mBaseValue = Formatter.stringToDouble(newValue);
}
public void handleReset() {
resetValues();
setValue("0");
setFormula("");
}
public void handleEquals() {
if (mLastKey.equals(Constants.EQUALS)) calculateResult();
if (!mLastKey.equals(Constants.DIGIT)) return;
mSecondValue = getDisplayedNumberAsDouble();
calculateResult();
mLastKey = Constants.EQUALS;
}
public void decimalClicked() {
String value = getDisplayedNumber();
if (!value.contains(".")) value += ".";
setValue(value);
}
public void zeroClicked() {
String value = getDisplayedNumber();
if (!value.equals("0")) addDigit(0);
}
private String getSign(String lastOperation) {
switch (lastOperation) {
case Constants.PLUS:
return "+";
case Constants.MINUS:
return "-";
case Constants.MULTIPLY:
return "*";
case Constants.DIVIDE:
return "/";
case Constants.MODULO:
return "%";
case Constants.POWER:
return "^";
case Constants.ROOT:
return "√";
}
return "";
}
public void numpadClicked(int id) {
if (mLastKey.equals(Constants.EQUALS)) mLastOperation = Constants.EQUALS;
mLastKey = Constants.DIGIT;
resetValueIfNeeded();
switch (id) {
case R.id.btn_decimal:
decimalClicked();
break;
case R.id.btn_0:
zeroClicked();
break;
case R.id.btn_1:
addDigit(1);
break;
case R.id.btn_2:
addDigit(2);
break;
case R.id.btn_3:
addDigit(3);
break;
case R.id.btn_4:
addDigit(4);
break;
case R.id.btn_5:
addDigit(5);
break;
case R.id.btn_6:
addDigit(6);
break;
case R.id.btn_7:
addDigit(7);
break;
case R.id.btn_8:
addDigit(8);
break;
case R.id.btn_9:
addDigit(9);
break;
default:
break;
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/calculator_holder"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.stins.calculator.MainActivity">
<TextView
android:id="@+id/formula"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2.1"
android:fontFamily="sans-serif-light"
android:gravity="right|bottom"
android:maxLines="1"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:textSize="@dimen/formula_text_size"/>
<TextView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.8"
android:fontFamily="sans-serif-light"
android:gravity="center_vertical|right"
android:maxLines="1"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:text="0"
android:textSize="@dimen/display_text_size"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="horizontal">
<Button
android:id="@+id/btn_modulo"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="mod"
android:textAllCaps="false"
android:textSize="@dimen/mod_text_size"/>
<Button
android:id="@+id/btn_power"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="^"/>
<Button
android:id="@+id/btn_root"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="√"/>
<Button
android:id="@+id/btn_clear"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="C"/>
<Button
android:id="@+id/btn_reset"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="AC"
android:visibility="gone"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="horizontal">
<Button
android:id="@+id/btn_7"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="7"/>
<Button
android:id="@+id/btn_8"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="8"/>
<Button
android:id="@+id/btn_9"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="9"/>
<Button
android:id="@+id/btn_divide"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="÷"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="horizontal">
<Button
android:id="@+id/btn_4"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="4"/>
<Button
android:id="@+id/btn_5"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="5"/>
<Button
android:id="@+id/btn_6"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="6"/>
<Button
android:id="@+id/btn_multiply"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="*"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="horizontal">
<Button
android:id="@+id/btn_1"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="1"/>
<Button
android:id="@+id/btn_2"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="2"/>
<Button
android:id="@+id/btn_3"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="3"/>
<Button
android:id="@+id/btn_minus"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="-"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="horizontal">
<Button
android:id="@+id/btn_0"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="0"/>
<Button
android:id="@+id/btn_decimal"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="."/>
<Button
android:id="@+id/btn_equals"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="="/>
<Button
android:id="@+id/btn_plus"
style="@style/MyButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="+"/>
</LinearLayout>
</LinearLayout>
logcat
02-11 14:27:36.485 5006-5006/com.example.stins.calculator E/AndroidRuntime:
FATAL EXCEPTION: main
Process: com.example.stins.calculator, PID: 5006
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.stins.calculator/com.example.stins.calculator.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.widget.TextView.getContext()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.widget.TextView.getContext()' on a null object reference
at me.grantland.widget.AutofitHelper.<init>(AutofitHelper.java:246)
at me.grantland.widget.AutofitHelper.create(AutofitHelper.java:62)
at me.grantland.widget.AutofitHelper.create(AutofitHelper.java:46)
at com.example.stins.calculator.MainActivity.onCreate(MainActivity.java:40)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
02-11 14:27:36.485 5006-5006/com.example.stins.calculator E/AndroidRuntime:
致命异常:主
进程:com.example.stins.calculator,PID:5006
java.lang.RuntimeException:无法启动activity ComponentInfo{com.example.stins.calculator/com.example.stins.calculator.MainActivity}:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“android.content.Context android.widget.TextView.getContext()
在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)上
位于android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
位于android.app.ActivityThread.-wrap11(ActivityThread.java)
在android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)上
位于android.os.Handler.dispatchMessage(Handler.java:102)
位于android.os.Looper.loop(Looper.java:148)
位于android.app.ActivityThread.main(ActivityThread.java:5417)
位于java.lang.reflect.Method.invoke(本机方法)
在com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run上(ZygoteInit.java:726)
位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
原因:java.lang.NullPointerException:尝试对空对象引用调用虚拟方法“android.content.Context android.widget.TextView.getContext()”
at me.grantland.widget.AutofitHelper.(AutofitHelper.java:246)
at me.grantland.widget.AutofitHelper.create(AutofitHelper.java:62)
at me.grantland.widget.AutofitHelper.create(AutofitHelper.java:46)
位于com.example.stins.calculator.MainActivity.onCreate(MainActivity.java:40)
位于android.app.Activity.performCreate(Activity.java:6237)
位于android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)上
位于android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
位于android.app.ActivityThread.-wrap11(ActivityThread.java)
在android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)上
位于android.os.Handler.dispatchMessage(Handler.java:102)
位于android.os.Looper.loop(Looper.java:148)
位于android.app.ActivityThread.main(ActivityThread.java:5417)
位于java.lang.reflect.Method.invoke(本机方法)
在com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run上(ZygoteInit.java:726)
位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
如果可能的话,有人知道如何帮助吗
我还包括了我的日志猫检查,以确保在
build.gradle
中有注释处理器
用于butterknife
设置。在依赖项下应该有一行如下所示:
annotationProcessor'com.jakewharton:butterknife编译器:8.5.1'
添加后,运行build->rebuild project。build>Clean project尝试删除该import com.example.stins.calculator
,但没有帮助。在那之后我进行了清理和重建。好的,请稍等,Josh,我实际上没有java类。它是一个小部件,被列为compile'me.grantland:autofittextview:0.2.+'
您想让我用CalcImpl java类编辑原始文章吗?如果有帮助的话,就是这样!非常感谢!但是现在按钮不再可以点击了。我不确定我是否在修复过程中解开了一些东西。这可能是在@style/MyButton
中,您缺少活动或按下的状态样式。事实上,我错了,android:state\u pressed=“true”
已经存在了,但是,正在单击的按钮没有将文本设置为文本视图。在您的主要活动中,方法setValue
和setFormula
没有做任何事情,我也没有看到任何应该对按钮单击做出反应的代码。只是重申我没有将MainActivity.java类的全部粘贴到代码段中。我现在刚编辑过。
02-11 14:27:36.485 5006-5006/com.example.stins.calculator E/AndroidRuntime:
FATAL EXCEPTION: main
Process: com.example.stins.calculator, PID: 5006
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.stins.calculator/com.example.stins.calculator.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.widget.TextView.getContext()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.widget.TextView.getContext()' on a null object reference
at me.grantland.widget.AutofitHelper.<init>(AutofitHelper.java:246)
at me.grantland.widget.AutofitHelper.create(AutofitHelper.java:62)
at me.grantland.widget.AutofitHelper.create(AutofitHelper.java:46)
at com.example.stins.calculator.MainActivity.onCreate(MainActivity.java:40)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)