이 글은 이것이 안드로이드다 with 코틀린(개정판)를 참고하여 작성하였습니다.
작성자 : 임나경
개발환경은 Windows, Android Studio입니다.
1. 쓰레드 타이머
1) 화면 준비
** "Hardcoded Text" warning 해결 방법
내용 : hardcoded string should use @string resource
[Android Studio] 경고(Warning): Hardcoded text - 해결
xml 파일을 열어 Design탭 Palette에서 Component Tree로 textView추가하니 생겼다. 노란색 경고 이미지를 클릭해보면 경고 메시지를 확인하고 해결할 수 있다. 1) 경고 이미지 Component Tree 경고 이미지 2) 메..
withthisclue.tistory.com
2) View Binding
<build.gradle> (:app)
buildFeatures {
viewBinding true
}
<MainActivity.kt>
package com.example.timer
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.timer.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
}
3) MainActivity.kt 수정
class MainActivity : AppCompatActivity() {
val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
// total, started 변수 선언
var total = 0
var started = false
// Handler import (Alt + Enter 이용)
val handler = object:Handler(Looper.getMainLooper()) {
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
}
Handler import 시 java.util.logging 말고 android.os를 선택한다.
handler 내부에서 ctrl + O 를 누른 뒤 handleMessage를 선택한다.
package com.example.timer
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import com.example.timer.databinding.ActivityMainBinding
import kotlin.concurrent.thread
class MainActivity : AppCompatActivity() {
val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
var total = 0
var started = false
val handler = object: Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) { // 스레드를 통해 total에 쓴 값을, msg를 통해 화면에 표시
val minute = String.format("%02d", total/60)
val second = String.format("%02d", total%60)
binding.textTimer.text = "$minute:$second"
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
with(binding) {
btnStart.setOnClickListener {
started = true
thread(start = true) { // sub thread
while (started) {
Thread.sleep(1000)
if (started) {
total += 1
handler?.sendEmptyMessage(0)
}
}
}
}
btnStop.setOnClickListener {
if(started){
started = false
total = 0
textTimer.text = "00:00"
}
}
}
}
}
- Thread.sleep() : 괄호 안의 수만큼 멈춤.
- thread(start = true) : Thread.sleep()을 sub thread에서 동작하게 하기 위해 thread(start = true)를 사용하여 함수 내부의 코드가 모두 sub thread에서 작동하게 함
runOnUiThread {
val minute = String.format("%02d", total/60)
val second = String.format("%02d", total%60)
binding.textTimer.text = "$minute:$second"
}
- runOnUiThread : 이 내부 코드는 메인 스레드에서 작동하게됨. 위의 코드에 handler부분을 아래 코드처럼 runOnUiThread를 이용해서 작성해도 됨.
4) 결과 화면
2. 코루틴 이미지 다운로드
1) 코루틴이란?
https://developer.android.com/kotlin/coroutines?hl=ko
Android의 Kotlin 코루틴 | Android 개발자 | Android Developers
Android의 Kotlin 코루틴 코루틴은 비동기적으로 실행되는 코드를 간소화하기 위해 Android에서 사용할 수 있는 동시 실행 설계 패턴입니다. 코루틴은 Kotlin 버전 1.3에 추가되었으며 다른 언어에서 확
developer.android.com
- 백그라운드 처리 구조
- 비동기적으로 실행되는 코드를 간소화하기 위해 Android에서 사용할 수 있는 동시 실행 설계 패턴
- 코루틴을 사용하여 이미지 주소를 입력하면 온라인에서 갖다가 화면에 보여주는 실습~
2) View Binding
위에 작성한 것과 동일한 방식으로 진행한다.
코루틴은 안스 or 코틀린 버전에 따라 dependency에 의존성 추가할지 확인해봐야함.
<build.gradle (:app)>
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
}
3) XML 수정
이미지와 프로그래스 바를 겹치게 하려면 xml을 코드를 수정해야한다.
<activity_main.xml>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyle" // 이 부분 수정
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" // 이 부분 수정
app:layout_constraintEnd_toEndOf="parent" // 이 부분 수정
app:layout_constraintStart_toStartOf="parent" // 이 부분 수정
app:layout_constraintTop_toTopOf="parent" /> // 이 부분 수정
visibility를 invisible 또는 gone으로 설정해서 처음에는 보이지 않도록 한다.
4) 함수 VS 메소드
클래스 안에 만드는 것은 메소드, 클래스 밖에 만드는 것은 함수이다.
5) MainActivity.kt 수정
- URL import 시 in android.provider... 말고 java.net으로 하기
- 메인 스레드는 화면을 다루는 코드들을 작성하기
package com.example.timer
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.provider.ContactsContract.CommonDataKinds.Website.URL
import android.view.View
import com.example.timer.databinding.ActivityMainBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.net.URL
import kotlin.concurrent.thread
class MainActivity : AppCompatActivity() {
val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
with(binding) {
btnDownload.setOnClickListener {
CoroutineScope(Dispatchers.Main).launch { // 코루틴의 메인 영역
progress.visibility = View.VISIBLE
val url = editUrl.text.toString()
val bitmap = withContext(Dispatchers.IO) {
loadImage(url) // bitmap을 꺼내서 저장. 백그라운드 실행
}
imagePreview.setImageBitmap(bitmap)
progress.visibility = View.INVISIBLE
}
}
}
}
}
suspend fun loadImage(imageUrl:String) : Bitmap {
val url = URL(imageUrl)
val stream = url.openStream()
return BitmapFactory.decodeStream(stream)
}
** hintTextColor not found 에러
내용 : AAPT: error: attribute android:hintTextColor not found.
해결책 : xml 파일에서 hintTextColor를 textColorHint로 수정한다.
6) 인터넷 권한 설정
<manifests/AndroidManifest.xml>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.timer">
<uses-permission android:name="android.permission.INTERNET"/> // 이 부분 추가
7) 결과 화면
'GDSC HUFS 3기 > Android with Kotlin Team 2' 카테고리의 다른 글
[2팀]31,32 Android 서비스, 포어그라운드 서비스 (0) | 2021.12.01 |
---|---|
[2팀] 33 Android 뮤직 플레이어 만들기 (0) | 2021.11.29 |
[2팀]16 Android와 SQLite 데이터 베이스 (0) | 2021.11.25 |
[2팀]16 파일 입출력 (0) | 2021.11.24 |
[2팀] 16-2 SharedPreference로 상태 값 지정하기 (0) | 2021.11.22 |