마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

안녕하세요 앱이 자꾸 튕겨서 질문 드립니다

0 추천

빌드 상에는 아무 문제가 없는데..

앱이 실행까지는 잘 되다가 몇번 버튼을 클릭하면 튕겨버리네요

문제가 뭔가 싶어서 문의드립니다

 

main 코드

package com.example.diceroller;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.Random;

public class MainActivity extends AppCompatActivity {

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

    public void myButtonListenerMethod() {
        Button button = (Button) findViewById(R.id.rollButton);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Random rand = new Random();
                int rollResult = rand.nextInt(6) + 1;
                TextView diceResult = (TextView) findViewById(R.id.diceResult);
                diceResult.setText(Integer.toString(rollResult));
                ImageView img = (ImageView) findViewById(R.id.diceImage);

                switch (rollResult) {
                    case 1:
                        img.setImageResource(R.drawable.dice1);
                        break;
                    case 2:
                        img.setImageResource(R.drawable.dice2);
                        break;
                    case 3:
                        img.setImageResource(R.drawable.dice3);
                        break;
                    case 4:
                        img.setImageResource(R.drawable.dice4);
                        break;
                    case 5:
                        img.setImageResource(R.drawable.dice5);
                        break;
                    case 6:
                        img.setImageResource(R.drawable.dice6);
                        break;
                }
            }
        });

    }
}

 

로그캣 입니다

2022-04-02 01:11:45.757 9646-9646/com.example.diceroller W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter androidx.vectordrawable.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
2022-04-02 01:11:45.694 9646-9646/? I/art: Late-enabling -Xcheck:jni
2022-04-02 01:11:45.694 9646-9646/? W/art: Unexpected CPU variant for X86 using defaults: x86
2022-04-02 01:11:45.728 9646-9646/com.example.diceroller W/System: ClassLoader referenced unknown path: /data/app/com.example.diceroller-2/lib/x86
2022-04-02 01:11:45.845 9646-9646/com.example.diceroller D/: HostConnection::get() New Host Connection established 0xab158140, tid 9646
2022-04-02 01:11:45.873 9646-9670/com.example.diceroller D/: HostConnection::get() New Host Connection established 0xab158800, tid 9670
2022-04-02 01:11:45.875 9646-9670/com.example.diceroller I/OpenGLRenderer: Initialized EGL, version 1.4
2022-04-02 01:11:45.875 9646-9670/com.example.diceroller D/OpenGLRenderer: Swap behavior 1
2022-04-02 01:11:45.875 9646-9670/com.example.diceroller W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
2022-04-02 01:11:45.875 9646-9670/com.example.diceroller D/OpenGLRenderer: Swap behavior 0
2022-04-02 01:11:45.890 9646-9670/com.example.diceroller D/EGL_emulation: eglCreateContext: 0xb5f051e0: maj 3 min 1 rcv 4
2022-04-02 01:11:45.920 9646-9670/com.example.diceroller D/EGL_emulation: eglMakeCurrent: 0xb5f051e0: ver 3 1 (tinfo 0xb5f031f0)
2022-04-02 01:11:45.922 9646-9670/com.example.diceroller E/eglCodecCommon: glUtilsParamSize: unknow param 0x000082da
2022-04-02 01:11:45.922 9646-9670/com.example.diceroller E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008cdf
2022-04-02 01:11:45.922 9646-9670/com.example.diceroller E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008824
2022-04-02 01:11:45.937 9646-9670/com.example.diceroller D/EGL_emulation: eglMakeCurrent: 0xb5f051e0: ver 3 1 (tinfo 0xb5f031f0)

 

늦은시간이지만 확인 부탁드랍니다 ㅠㅠ

 

rascus (120 포인트) 님이 2022년 4월 2일 질문
올리신 로그는 앱크래시와는 상관이 없어 보이는 것 같은데... 안드로이드 스튜디오 로그캣에서 로그레벨을 에러로, 해당 애플리케이션에 대한 필터로 변경하신 다음 다음 다시 캡쳐해 보시겠어요?

1개의 답변

0 추천

관련은 없지만 올리신 코드를 좀 더 읽기 쉬운 형태로 업데이트하시면 어떨까 싶습니다.

먼저 액티비티에 있는 뷰를 private member로 변경해서 한번만 변수를 초기화 하고 여러군데서 재사용하도록 했습니다.
그리고  rollButton 이벤트 리스너도 rollDice()라는 private method를 만들어 위임했습니다. 이유는 redability(가독성)입니다.
버튼클릭 리스너 안에 로직을 다 집어넣을 경우 해당 버튼 클릭이 무얼하는지 이해하려면 코드를 다 읽어야 하기 때문입니다.
rollDice()라는 메소들 사용함으로써 rollDice()메소드 내용을 보지 않더라도 해당 버튼을 누르면 "주사위를 굴린다"고 금방 이해 할 수 있습니다.

public class MainActivity extends AppCompatActivity {

  private ImageView diceImage;
  private TextView diceNumberText;
  private Button rollButton;

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

        bindViews();
    }

  private void bindViews() {
      diceImage = findViewById(R.id.diceImage);
      diceNumberText = findViewById(R.id.diceResult);
      rollButton = findViewById(R.id.rollButton); 
      rollButton.setOnClickLisetner(v -> rollDice());
  }

  private void rollDice() {
     
  }
}

 

이제, rollDice() 를 구현할 차례입니다. 잘 생각해 보시면 주사위 번호를 랜덤하게 생성하는 코드는 화면과는 관계없는 일종의 비지니스 로직입니다. 따라서 이 로직이 변경될 때는 관련된 부분만 변경하는 것이 좋고 뷰와는 다른 역할이므로, 별도의 클래스를 만드는 것이 타당해 보입니다. 이렇게 하면 추후 로직 변경도 쉽고 단위테스틀 작성할 때도 쉬워집니다.

public static class DiceNumberGenerator {  
        private final Random random = new Random();

        public int next() {
            return random.nextInt(7) + 1;
        }
}

 

이제 DiceNumberGenerator 를 MainActivity에서 사용하면 되는데, 기존의 코드를 보시면 생성된 넘버에 따라 이미지 리소스를 매핑하는 부분이 좀 복잡합니다. 리소스의 갯수가 늘어나거나 하면 더 복잡해 지겠죠. 이럴 때 사용할 수 있는 것이 매핑테이블인데,
enum 같은 구조를 사용하면 훨씬 깔끔해 집니다.

package network;

public enum DiceNumberType {
    ONE(1, R.drawable.dice1),
    TWO(2, R.drawable.dice2),
    THREE(3, R.drawable.dice3),
    FOUR(4, R.drawable.dice4),
    SIX(5, R.drawable.dice5),
    SEVEN(6, R.drawable.dice6);

    private final int value;
    private final int drawableId;

    DiceNumberType(int value, int drawableId) {
        this.value = value;
        this.drawableId = drawableId;
    }

    public int getValue() {
        return value;
    }

    public int getDrawableId() {
        return drawableId;
    }
    
    @Nullable
    public static DiceNumberType byValue(int value) {
        for (DiceNumberType diceNumberType : values()) {
            if (diceNumberType.getValue() == value) {
                return diceNumberType;
            }
        }
        return null;
    }
}

 

이제 MainActivity의 rollDice()를 구현합니다.

public class MainActivity extends AppCompatActivity {

  ...
   
  private DiceNumberGenerator diceNumberGenerator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...

        diceNumberGenerator = new DiceNumberGenerator();
        bindViews();
    }

  private void bindViews() {
      ...
  }

  private void rollDice() {
       int diceNumber = diceNumberGenerator.next();
       DiceNumberType diceNumberType = Objects.requireNonNull(DiceNumberType.byValue(diceNumber));
       
       diceNumberText.setText("" + diceNumberType.getValue());
       diceImage.setImageResource(diceNumberType.getDrawableId());
  }
}

 

spark (227,530 포인트) 님이 2022년 4월 2일 답변
...