您好我最近一直在使用Android计算器应用程序,它几乎已经完成,但现在当点击时数字和其他运算符崩溃时会遇到一些问题。然后整个应用程序崩溃。上面的代码如下:
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"
android:longClickable="true"/>
<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>
MainActivity.java
package com.example.stins.calculator;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.example.stins.calculator.Calculator;
import com.example.stins.calculator.CalculatorImpl;
import com.example.stins.calculator.Config;
import com.example.stins.calculator.Constants;
import com.example.stins.calculator.Formatter;
import com.example.stins.calculator.Utils;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnLongClick;
import me.grantland.widget.AutofitHelper;
public class MainActivity extends SimpleActivity implements Calculator {
@BindView(R.id.result)
TextView mResult;
@BindView(R.id.formula)
TextView mFormula;
private static CalculatorImpl mCalc;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
CalculatorImpl calc = new CalculatorImpl(this);
AutofitHelper.create(mResult);
AutofitHelper.create(mFormula);
}
@OnClick(R.id.btn_plus)
public void plusClicked() {
mCalc.handleOperation(Constants.PLUS);
}
@OnClick(R.id.btn_minus)
public void minusClicked() {
mCalc.handleOperation(Constants.MINUS);
}
@OnClick(R.id.btn_multiply)
public void multiplyClicked() {
mCalc.handleOperation(Constants.MULTIPLY);
}
@OnClick(R.id.btn_divide)
public void divideClicked() {
mCalc.handleOperation(Constants.DIVIDE);
}
@OnClick(R.id.btn_modulo)
public void moduloClicked() {
mCalc.handleOperation(Constants.MODULO);
}
@OnClick(R.id.btn_power)
public void powerClicked() {
mCalc.handleOperation(Constants.POWER);
}
@OnClick(R.id.btn_root)
public void rootClicked() {
mCalc.handleOperation(Constants.ROOT);
}
@OnClick(R.id.btn_clear)
public void clearClicked() {
mCalc.handleClear();
}
@OnLongClick(R.id.btn_clear)
public boolean clearLongClicked() {
mCalc.handleReset();
return true;
}
@OnClick(R.id.btn_equals)
public void equalsClicked() {
mCalc.handleEquals();
}
@OnClick({R.id.btn_decimal, R.id.btn_0, R.id.btn_1, R.id.btn_2, R.id.btn_3, R.id.btn_4, R.id.btn_5, R.id.btn_6, R.id.btn_7, R.id.btn_8,
R.id.btn_9})
public void numpadClick(View view) {
//Toast.makeText(this, "click handler called", Toast.LENGTH_SHORT).show();
numpadClicked(view.getId());
}
public void numpadClicked(int id) {
mCalc.numpadClicked(id);
}
@Override
public void setValue(String value) {
mResult.setText(value);
}
@Override
public void setValueDouble(double d) {
mCalc.setValue(Formatter.doubleToString(d));
mCalc.setLastKey(Constants.DIGIT);
}
public void setFormula(String value) {
mFormula.setText(value);
}
public CalculatorImpl getCalc() {
return mCalc;
}
}
CalculatorImpl.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;
}
}
}
logcat的
02-11 20:18:59.116 6438-6438/com.example.stins.calculator E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.stins.calculator, PID: 6438
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.stins.calculator.CalculatorImpl.numpadClicked(int)' on a null object reference
at com.example.stins.calculator.MainActivity.numpadClicked(MainActivity.java:105)
at com.example.stins.calculator.MainActivity.numpadClick(MainActivity.java:101)
at com.example.stins.calculator.MainActivity_ViewBinding$16.doClick(MainActivity_ViewBinding.java:192)
at butterknife.internal.DebouncingOnClickListener.onClick(DebouncingOnClickListener.java:22)
at android.view.View.performClick(View.java:5198)
at android.view.View$PerformClick.run(View.java:21147)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
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)
我似乎无法找到导致程序崩溃的原因。有谁看到了什么?我感谢任何和所有的帮助!
答案 0 :(得分:0)
删除此行:
CalculatorImpl calc = new CalculatorImpl(this);
并替换为:
mCalc = new CalculatorImpl(this);