Как решить проблемы с памятью стека?

#java #android

#java #Android

Вопрос:

я пытаюсь создать приложение для Android, которое позволяет пользователям выполнять некоторые вычисления за ограниченное время. Код работал хорошо, пока я не разделил код на две части и не создал другой класс для выполнения другой задачи.

Я импортировал все соответствующие пакеты и файлы классов в новый класс.В коде не было ошибок, но когда я запускаю приложение, оно вылетает.Я много раз пытался изменить код, но безрезультатно. Код работает хорошо, когда я объединяю весь код в один класс.

я получаю ошибку «java.lang.Ошибка StackOverflowError: размер стека 8 МБ по номеру строки »

         **MainActivity.java**



                        package e.nani.firstattempt;

                        import android.content.Context;
                        import android.os.AsyncTask;
                        import android.os.Bundle;
                        import android.os.CountDownTimer;
                        import android.os.Vibrator;
                        import android.support.v7.app.AlertDialog;
                        import android.support.v7.app.AppCompatActivity;
                        import android.util.Log;
                        import android.view.View;
                        import android.widget.Button;
                        import android.widget.TextView;
                        import android.widget.Toast;



                        import java.util.Random;

                        public class MainActivity extends AppCompatActivity {
                        public int a1;//random num 1
                        public int a2;//random num 2;
                        public   TextView textview;
                        public Button b1;
                        public Button b2;
                        public   Button b3;
                        public Button b4;
                        public int option1;
                        public int option2;
                        public   int option3;
                        public   int option4;
                        public int score=0;
                        TextView scoreid;
                        int numberofquestions=10;
                        TextView time;
                        public   int answers[]=new int[4];
                       Logic  c=new Logic();

                        @Override
                        protected void onCreate(Bundle savedInstanceState) {
                        super.onCreate(savedInstanceState);
                        setContentView(R.layout.activity_main);
                        textview=(TextView)findViewById(R.id.sum);
                        b1=(Button)findViewById(R.id.option1);
                        b2=(Button)findViewById(R.id.option2);
                        b3=(Button)findViewById(R.id.option3);
                        b4=(Button)findViewById(R.id.option4);
                        time=(TextView)findViewById(R.id.timer);

                        scoreid=(TextView)findViewById(R.id.scoreid) ;
                        scoreid.setText((0 "/" numberofquestions));


                        c.operatio();

                        timer.start();

                        }


                        public void operation(View V)
                        {
                        try{
                        switch(V.getId()) {
                        case R.id.option1:

                        if (b1.getText().equals(Integer.toString(option4))) {
                        score = score   1;
                             c.operatio();
                        scoreid.setText((score  "/"  numberofquestions));
                        } else {

                        Toast.makeText(this, "wrong answer", Toast.LENGTH_SHORT).show();
                        Vibrator vibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
                        vibrator.vibrate(500);
                        c.operatio();
                        }
                        break;
                        case R.id.option2:


                        if (b2.getText().equals(Integer.toString(option4))) {
                        score = score   1;
                        c.operatio();
                        scoreid.setText(score "/"  numberofquestions);
                        } else
                        {

                        Toast.makeText(this, "wrong answer", Toast.LENGTH_SHORT).show();
                        Vibrator vibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
                        vibrator.vibrate(500);
                        c.operatio();
                        }
                        break;
                        case R.id.option3:
                        if (b3.getText().equals(Integer.toString(option4))) {
                        score = score   1;
                        c.operatio();
                        scoreid.setText((score "/"  numberofquestions));
                        } else
                        {
                        Toast.makeText(this, "wrong answer", Toast.LENGTH_SHORT).show();
                        Vibrator vibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
                        vibrator.vibrate(500);
                        c.operatio();
                        }
                        break;

                        case R.id.option4:
                        if (b4.getText().equals(Integer.toString(option4))) {
                        score = score   1;
                        c.operatio();
                        scoreid.setText(score "/"  numberofquestions);
                        } else
                        {
                        Toast.makeText(this, "wrong answer", Toast.LENGTH_SHORT).show();
                        Vibrator vibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
                        vibrator.vibrate(500);
                        c.operatio();
                        }

                        break;
                        }



                        }
                        catch(Exception e)
                        {
                        e.printStackTrace();
                        }
                        }





                        CountDownTimer timer=new CountDownTimer(30000, 1000) {

                        public void onTick(long millisUntilFinished) {
                        time.setText("seconds remaining: "   millisUntilFinished / 1000);
                        }

                        public void onFinish() {
                        time.setText("done!");
                        }
                        };


                        }
 

Logic.java

                          package e.nani.firstattempt;
                        import java.util.Random;

                        class Logic {
                            MainActivity s=new MainActivity();
                            public void operatio() {
                                try {
                                        Random n = new Random();
                                        int n1 = n.nextInt(4);
                                        int n2 = n.nextInt(4);
                                        int n3 = n.nextInt(4);
                                        int n4 = n.nextInt(4);

                                        s.a1 = n.nextInt(51);
                                        s.a2 = n.nextInt(35);
                                        s.option1 = n.nextInt((s.a1   s.a2)   1);

                                        s.option2 = n.nextInt((s.a1   s.a2)   1);
                                        s.option3 = n.nextInt((s.a1   s.a2)   1);
                                        s.option4 = s.a1   s.a2;


                                        s.answers[n1] = s.option1;
                                        while (n2 == n1) {
                                            n2 = n.nextInt(4);
                                        }
                                        while (s.option2 == s.option1 || s.option2 == s.option4) {

                                            s.option2 = n.nextInt((s.a1   s.a2)   1);

                                        }


                                        s.answers[n2] = s.option2;
                                        while (s.option3 == s.option2 || s.option3 == s.option1 || s.option3 == s.option4)


                                        {
                                            s.option3 = n.nextInt((s.a1   s.a2)   1);
                                        }


                                        while (n3 == n2 || n3 == n1)

                                        {
                                            n3 = n.nextInt(4);
                                        }

                                        s.answers[n3] = s.option3;

                                        while (n4 == n2 || n4 == n1 || n4 == n3) {
                                            n4 = n.nextInt(4);
                                        }
                                        s.answers[n4] = s.option4;


                                        s.b1.setText(Integer.toString(s.answers[0]));
                                        s.b2.setText(Integer.toString(s.answers[1]));
                                        s.b3.setText(Integer.toString(s.answers[2]));
                                        s.b4.setText(Integer.toString(s.answers[3]));
                                        s.textview.setText(s.a1   " "   s.a2);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
 

Главный вопрос здесь в том, почему приложение работает нормально, когда код находится только в основном классе, но не работает, когда какой-то код написан в другом классе?
Спасибо.

Комментарии:

1. Какова точная ошибка с трассировкой?

2. java.lang. Ошибка StackOverflowError: размер стека 8 МБ в строке номер 37 … Это основная ошибка @Carcigenicate

3. Два метода являются взаимно рекурсивными без завершения; остальное должно быть очевидно?

4. Да, я это исправил. Но теперь эта строка ** » s.b1.setText(Integer.toString(s.answers[0]));» ** содержит ошибку. Ошибка заключается в том, что в классе Login существует исключение nullpointer из этой строки. ошибка гласит: «попытка вызвать виртуальный метод «s.b1.setText(Integer.toString(s.answers[0]))» «. Может кто-нибудь помочь мне с этим. Спасибо. @другое-Дэйв

Ответ №1:

В вашем MainActivity у вас есть переменная c с логикой типа, которая создается. Но в вашем логическом классе есть переменная типа MainActivity, которая пытается создать экземпляр класса MainActivity. В двух словах, в классе A вы создаете экземпляр класса B, который устанавливает класс A и так далее… Кстати, вы не можете создавать экземпляры классов AppCompatActivity напрямую. Так что удалите MainActivity s=new MainActivity(); в своем Logic.class .

Надеюсь, я смогу вам помочь.

Комментарии:

1. Спасибо, это хорошее объяснение. Как мне получить доступ к значениям переменных, объявленных в MainActivity.java без создания его экземпляра ? Должен ли я расширить MainActivity из логического класса или есть какой-либо другой способ? @Csongi77

2. Единственной целью и обязанностью MainActivity является отображение значений (текстов, изображений и т. Д.) Вы должны создать ViewModel, который содержит логику и входные значения, введенные в MainActivity. В этом случае вы не потеряете значения, когда ваша активность будет уничтожена (например, в случае входящего вызова, поворота устройства из книжной в альбомную и т. Д.). В двух словах, поместите логику в ViewModel отдельно от Activity. Для получения дополнительной информации о жизненном цикле Activity, класс ViewModel: developer.android.com/reference/android/app/Activity , developer.android.com/topic/libraries/architecture/viewmodel