본문 바로가기

대외활동/UMC

[UMC 2기] Android 파트 4주차 정리

복습 및 정리

Thread

A thread is a path of execution within a process.

프로세스 내부에서 일하는 주체

++ 프로세스 - 컴퓨터에서 연속적으로 실행되고 있는 프로그램

++ 프로그램 - 어떤 작업을 위해 실행할 수 있는 파일

Thread는 동기적? 비동기적?

Single Thread - 동기(synchronous)

Multi Thread - 비동기(asynchronous)

동기 - 하나의 흐름으로 순차적으로 진행

비동기 - 여러가지의 일이 동시에 수행되는 것

Thread in Android Studio

1. Main Thread

안드로이드 OS에서 자동으로 만들어준 쓰레드

View Control, Vew Rendering

UI작업은 Main Thread에서만 해야 함

UI Thread라고도 함

Main Thread에서 무거운 작업은 하지 않는 게 좋다.

 

2. Worker Thread

View Control, View Rendering

 

Worker Thread에서 View를 Rendering하고자 한다면 Main Thread에 UI를 update해주라는 요청을 해주어야 한다. 요청방법에는 (1) 핸들러 사용, (2) 액티비티 내부 함수 사용 이 있다.

 

(1) 핸들러 사용

package com.example.thread

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import com.example.thread.databinding.ActivityMainBinding


class MainActivity : AppCompatActivity() {

    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val handler = Handler(Looper.getMainLooper())

        val imageList = arrayListOf<Int>()

        imageList.add(R.drawable.ic_launcher_background)
        imageList.add(R.drawable.ic_launcher_foreground)
        imageList.add(R.drawable.ic_launcher_background)
        imageList.add(R.drawable.ic_launcher_foreground)

        Thread{
            for(image in imageList){
                handler.post {
                    binding.iv.setImageResource(image)
                }
                Thread.sleep(2000)
            }
        }.start()
    }
}

 

(2) 액티비티 내부 함수 사용

package com.example.thread

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import com.example.thread.databinding.ActivityMainBinding


class MainActivity : AppCompatActivity() {

    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val imageList = arrayListOf<Int>()

        imageList.add(R.drawable.ic_launcher_background)
        imageList.add(R.drawable.ic_launcher_foreground)
        imageList.add(R.drawable.ic_launcher_background)
        imageList.add(R.drawable.ic_launcher_foreground)

        Thread{
            for(image in imageList){
                runOnUiThread{
                    binding.iv.setImageResource(image)
                }
                Thread.sleep(2000)
            }
        }.start()
    }
}

 

Handler

A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue.

Handler는 특정 메세지를 Looper의 MessageQueue에 넣거나 Looper가 MessageQueue에서 특정 메세지를 꺼내어 전달하면 이를 처리하는 기능을 수행한다.

 

Looper

Looper is a class which is used to execute the Messages(Runnables) in a queue

하나의 쓰레드에는 오직 하나의 Looper를 가진다.

각 쓰레드 Looper 내부에는 MessageQueue라는 것이 존재한다. 여기에는 해당 쓰레드가 처리해야 할 동작들이 Message 라는 형태로 하나씩 쌓이게 된다.

안드로이드에서는 MainActivity가 실행됨과 동시에 자동으로 Main thread의 Looper가 돌기 시작한다.

Looper는 궁극적으로 MessageQueue에 들어오는 메세지들을 하나씩 꺼내어 이를 적절한 Handler로 전달하는 역할을 한다.

 

Splash Activity

앱 실행 시 로딩 화면을 구성하기 위해 만드는 Activity

Splach Activity를 구현하는 방법에는 (1) handler 사용, (2) 시작테마 적용 이 있다.

 

(1) halndler 사용

지정된 시간동안 무조건 화면을 보여주기 때문에 UX적으로 불필요하게 사용자의 시간을 빼앗을 수 있음

package com.example.flo

import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import com.example.flo.databinding.ActivitySplashBinding

class SplashActivity: AppCompatActivity() {

    lateinit var binding : ActivitySplashBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivitySplashBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val handler = Handler(Looper.getMainLooper())

        handler.postDelayed({
            startActivity(Intent(this,MainActivity::class.java))
        }, 1000)
    }
}

 

(2) 시작테마 적용(권장)

1. drawable 폴더에 splash.xml 파일 생성

2. values 폴더 안에 있는 themes 폴더 안에 themes.xml 파일에 아래 코드 추가

<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:windowBackground">@drawable/splash</item>
</style>

3. AndroidManifest.xml 파일에 mainactivity에 android:theme="@style/SplashTheme" 추가

4. MainActivity 파일에 onCreate에 “setTheme(R.style.Theme_FLO)” 추가

 

Else

NULL 처리

? → nullable 타입, null이 아니면 그대로 반환, null이면 null 반환

?: → null이 아니면 그대로 반환, null이면 이 연산자의 오른쪽에 정의한 것을 반환

!! → 이것은 null이 될 수 없다고 단언

inner class

자바 같은 경우 class 안에 class를 선언하면 내부클래스로 인식

코틀린의 경우 class 안에 class를 선언하면 정적인 클래스로 인식 → 그래서 내부클래스로 만들 경우 class를 선언할 때 앞에 inner를 붙어주어야 함

 

참조

https://hyuncb.tistory.com/5

https://brunch.co.kr/@mystoryg/84

https://velog.io/@haero_kim/Android-Looper-Handler-%EA%B8%B0%EC%B4%88-%EA%B0%9C%EB%85%90

https://kotlinlang.org/docs/null-safety.html#nullable-types-and-non-null-types

https://itmining.tistory.com/5