3
\$\begingroup\$

A few days ago, I uploaded my first version of my calculator app I made in android studio. I got some great some feedback on it and tried to improve my app as much as I could.

changes/new featres:

  • Implemented a delete button
  • optimized the way, everything is calculated
  • Made a seperate class for the calculator

Here u can see how the app looks 1

Here is the code from the my MainActivity.java

package com.example.calculatormk2;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    Calculator calculatorMain = new Calculator();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onNumberClick(View view) {
        calculatorMain.addDigitToInput(getTextFrom(view));
        updateTextView();
    }

    public void onOperatorClick(View view) {
        calculatorMain.addOperatorToInput(getTextFrom(view));
        updateTextView();
    }

    public void onEqualsClick(View v) {
        TextView mainOutput = findViewById(R.id.mainOutput);
        mainOutput.setText(calculatorMain.calculate());
    }

    public void onDeleteClick(View v) {
        calculatorMain.delete();
        updateTextView();
    }

    public String getTextFrom(View v) {
        return ((Button) v).getText().toString();
    }

    public void updateTextView() {
        TextView mainOutput = findViewById(R.id.mainOutput);
        mainOutput.setText(calculatorMain.getInput());
    }
}

And here is the code from my Calculator.java

package com.example.calculatormk2;

import java.util.ArrayList;
import java.util.Arrays;

public class Calculator {
    private StringBuilder inputAsText = new StringBuilder();
    private ArrayList inputAsArrayList;

    public void addDigitToInput(String digit) {
        inputAsText.append(digit);
    }

    public void addOperatorToInput(String operator) {
        inputAsText.append(" ").append(operator).append(" ");
    }

    public void delete() {
        if (inputAsText.length() != 0) {
            if (Character.isWhitespace(inputAsText.charAt(inputAsText.length() - 1))) {
                inputAsText.deleteCharAt(inputAsText.length() - 1);
                inputAsText.deleteCharAt(inputAsText.length() - 1);
                inputAsText.deleteCharAt(inputAsText.length() - 1);
            } else {
                inputAsText.deleteCharAt(inputAsText.length() - 1);
            }
        }
    }

    public void clearInput() {
        inputAsText.delete(0, inputAsText.length());
        inputAsArrayList.clear();
    }

    public String getInput() {
        return this.inputAsText.toString();
    }

    public String calculate() {
        String[] tmpArray = inputAsText.toString().split(" ");
        inputAsArrayList = new ArrayList(Arrays.asList(tmpArray));
        inputAsArrayList = calculateFor("x", "÷");
        inputAsArrayList = calculateFor("+", "-");
        String answer = String.valueOf(inputAsArrayList.get(0));
        clearInput();
        return answer;
    }

    public ArrayList calculateFor(String operator1, String operator2) {
        while (inputAsArrayList.contains(operator1) || inputAsArrayList.contains(operator2)) {

            int indexOperator1 = inputAsArrayList.indexOf(operator1);
            int indexOperator2 = inputAsArrayList.indexOf(operator2);
            int indexOperatorMain = Math.min(indexOperator1, indexOperator2);

            if (indexOperator1 == -1) {
                indexOperatorMain = indexOperator2;
            } else if (indexOperator2 == -1) {
                indexOperatorMain = indexOperator1;
            }

            String operatorMain = inputAsArrayList.get(indexOperatorMain).toString();

            double firstNumber = Double.parseDouble(inputAsArrayList.get(indexOperatorMain - 1).toString());
            double secondNumber = Double.parseDouble(inputAsArrayList.get(indexOperatorMain + 1).toString());

            double answer = calculateSegment(firstNumber, secondNumber, operatorMain);

            inputAsArrayList.remove(indexOperatorMain - 1);
            inputAsArrayList.remove(indexOperatorMain - 1);
            inputAsArrayList.remove(indexOperatorMain - 1);
            inputAsArrayList.add(indexOperatorMain - 1, answer);
        }
        return inputAsArrayList;
    }

    public double calculateSegment(double fNumber, double sNumber, String o) {
        switch (o) {
            case "x":
                return fNumber * sNumber;
            case "÷":
                return fNumber / sNumber;
            case "+":
                return fNumber + sNumber;
            default:
                return fNumber - sNumber;
        }
    }
}

Im not sure if I want to make a 3rd version or move on to another project. (after ive learned more about android development) For a 3rd version, I really would like to implement a history that keeps track of all the calculations and answers and possibly also allow the ability to use a square root.

One thing I could not figure out, is how to implement multithreading in my app. I wanted to calculate the answers on a different thread. (Start a new thread at the calculate() function) But I didnt know how to return my answer. This probably is useless because the calculations doenst even take 1 second, but it would be some great practise for later projects. Anyways, any feedback/suggestions on my app are welcome. Thanks for reading!

(Git repository: https://github.com/PhilipNousPXL/Calculator-mk2.git)

\$\endgroup\$
2
  • \$\begingroup\$ this looks much better than your previous Code... Especially your MainActivity ;-) \$\endgroup\$ Feb 14, 2022 at 5:32
  • \$\begingroup\$ using List<Strings> as data model is ambigous - you should use an more OOP-approach. look at this tutorial to see some objects - where you have strings \$\endgroup\$ Feb 14, 2022 at 15:19

1 Answer 1

2
\$\begingroup\$

thanks for sharing your progress - looks far better than v1, gratulations :-)

about history

instead of a mere result-history i would advise you to create an input-history. Other people have already struggles with such an challange and created an Command Design Pattern from the GoF (Gang of four). Put your commands on a stack and you have a history - includng undo/redo!

side note

  • A Command would help you to stick with the Separation of Concerns since you would put these part of your code together that belong together.
  • A Command would help you to stick with the Open Closed Principle since it would be very easy to create other command (as mentioned from you: a square root command?!)

about concurrency

if you have a time consuming process that should run aside from your GUI thread (in android) you should have a closer look at the Executors and Handlers (a very small tutorial is found here) - i am sorry that i cannot provide any details before you have tried to implement it.

OOP calculator

well that might be an never endig story, see this articel about oop calculator.

This is a medium difficulty problem in Leetcode. This is medium only if you are talking in terms of algorithm and time complexity. But let’s say you have to build a calculator for an enterprise. The calculator that will be extensible, maintainable and optimized at the same time.

So maybe this might be too much for now (since you said you are rather novice, first year? or so?)

But with an OOP approach you could at least try to get rid of your input model ArrayList<String> inputAsArrayList - which is really a pain.

cool stuff

you really did clean up your MainActivity - now it really looks cool and you may be very proud of you in doing it this way!!! keep up that spirit!!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.