#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