4th Development Log

15962 단어 androidSSACSSAC

💡 멀티스레드를 활용하여 앱 만들어보기

  • 게임, 플레이어, 네트워크 활용 등 활용 방식은 무관

✔️ 실습 영상
https://youtu.be/1wZzW1abDm4

✔️ 레퍼런스


SharedPreferences

Context.getSharedPreferences(String, int) 에서 반환된 기본 설정 데이터에 액세스하고 수정하기 위한 인터페이스

  • 앱의 데이터를 저장 및 관리해야 할 때 그 데이터가 중요한 데이터가 아닌 간단한 설정값이나 문자열 등일 경우, DB 에 저장하는 대신 안드로이드에서 기본적으로 제공하는 SharedPreferences 를 사용하여 관리하면 편리함
  • 데이터를 타입에 따라 관리하며, 데이터는 앱 내 폴더에 파일로 저장되므로 앱을 삭제하면 데이터도 삭제됨
private fun setScore() {
        val score = intent.extras!!.getInt("score")
        val sharedPreference = getSharedPreferences("ScoreInformation", 0)
        var highestScore = sharedPreference.getInt("HighestScore", 0)
        val editor = sharedPreference.edit()

        if (score > highestScore) {
            highestScore = score
            editor.putInt("HighestScore", highestScore)
            editor.apply()
        }

        tvScore = findViewById(R.id.tv_initialScore)
        tvHighestScore = findViewById(R.id.tv_initialHighestScore)
        tvScore!!.text = score.toString()
        tvHighestScore!!.text = highestScore.toString()
}

companion object

어떤 클래스의 모든 인스턴스가 공유하는 객체를 만들고 싶을 때 사용

  • java 와 달리 kotlin 에는 static 이 없음, 클래스 인스턴스 없이 어떤 클래스 내부에 접근하고 싶다면 클래스 내부에 객체를 선언할 때 companion object 를 사용하면 됨
  • 클래스 당 하나만 가질 수 있음
    • @JvmStatic
      Companion 에 등록된 변수를 자바의 static 처럼 선언하기 위한 annotation
      static 변수의 get() / set() 함수를 자동으로 만들라는 의미
	//나는 이런 식으로 사용했다!
        companion object {

              var screenWidth: Int = 0
              var screenHeight: Int = 0

              @JvmStatic
              var spaceShipWidth: Int = 0

              @JvmStatic
              var spaceShipHeight: Int = 0
          }

          screenWidth = point.x
          screenHeight = point.y

          spaceShipWidth = spaceShip.width	//== spaceShip.getWidth()
          spaceShipHeight = spaceShip.height	//== spaceShip.getHeight()

onDraw()

커스텀 뷰 그리기에서 가장 중요한 단계는 onDraw() 메서드를 재정의하는 것

  • onDraw() 의 매개변수는 뷰에서 자기 자신을 그릴 때 사용할 수 있는 Canvas 객체
  • onDraw() 를 호출하려면 먼저 Paint 객체를 만들어야 함
    • Paint
      • android.graphics 프레임워크는 그리기 작업을 두 영역으로 나눈다
      • 그리는 내용(Canvas에서 처리)
      • 그리기 방법(Paint에서 처리)
        • ex) Canvas 는 선을 그릴 수 있는 메서드를 제공하고 Paint 는 선의 색상을 정의하는 메서드를 제공한다. Canvas 에는 직사각형을 그리는 메서드가 있는 반면 Paint 는 직사각형을 색으로 채울지 또는 비워 둘지 정의한다. 간단히 말해, Canvas 는 화면에 그릴 수 있는 도형을 정의하고, Paint 는 그리는 각 도형의 색상, 스타일, 글꼴 등을 정의한다.
          -> 따라서, 무엇을 그리기 전에 하나 이상의 Paint 객체를 만들어야 한다.
override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        canvas.drawBitmap(spaceShip, spaceShipX, spaceShipY, null)
        canvas.drawText("Score: " + (hitTargetCount * 10), 0f, TEXT_SIZE.toFloat(), scorePaint)
        canvas.drawRect(
            (screenWidth - 130).toFloat(),
            10f,
            (screenWidth - 130 + 10 * lives).toFloat(),
            TEXT_SIZE.toFloat(),
            healthPaint
        )
        handlerObject.postDelayed(runnable, UPDATE_MILLI_SECONDS)
}

개체를 미리 만드는 것은 중요한 최적화 작업이다. 뷰를 다시 그리는 경우는 매우 자주 발생하며 다수의 그리기 객체는 많은 비용을 들여 초기화해야 한다. 따라서, onDraw() 내에서 그리기 객체를 만들면 성능이 크게 저하되고 UI 가 느리게 표시될 수 있다.

Thread, Handler

스레드란 하나의 프로세스 안에서 실행되는 여러 흐름의 단위

  • 메인 스레드 이외의 스레드는 UI를 업데이트할 수 없음(접근할 수 없음)
  • ANR 발생 가능
    단일 스레드에서 앱이 리소스를 많이 소모하는 작업을 수행하는 경우, 네트워크 액세스나 데이터베이스 쿼리 등의 긴 작업을 수행할 때 전체 UI가 차단된다. 스레드가 차단되면 모든 이벤트가 발생하지 않아 사용자에게는 애플리케이션이 중단된 것처럼 보인다. 심각한 경우, UI 스레드가 몇 초 이상 차단되면(현재 약 5초) 사용자에게 "애플리케이션이 응답하지 않습니다"(ANR)라는 대화상자가 표시될 수 있다.
    • Handler
      • 메인 스레드 이외의 스레드에서도 UI 를 변경 가능하게 해줌(접근은 역시 불가능)
      • 자신의 스레드와 다른 스레드에서 수행할 작업을 대기열에 추가하여 순서대로 처리함
var mediaPlayer: MediaPlayer? = null

    private var handler = Handler(Looper.getMainLooper())
    
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        thread {
            handler.post {
                mediaPlayer = MediaPlayer.create(this, R.raw.background_music)
                mediaPlayer!!.isLooping   //무한재생
                mediaPlayer!!.start()
            }
        }
    }

cf. 스레드와 관련한 간단한 예제는 https://velog.io/@morgankim/4th-Development-Practice 참고!

➕ AsyncTask 사용해보기!

MediaPlayer

  • SoundPool
    • 장점
      짧은 사운드 재생에 효과적 (10초 내)
      사운드 연타 구현 가능
    • 단점
      긴 사운드 재생 불가
      3gp 재생불가, mp3 재생 불안정, ogg 재생은 안정적

  • MediaPlayer
    • 장점
      긴 사운드 재생에 효과적
    • 단점
      연타 처리의 어려움

좋은 웹페이지 즐겨찾기