*코루틴(Coroutine)-구현하기(이미지 다운로드 앱)
-build.gradle
-- android{} 에 뷰바인딩 추가
//뷰바인딩
buildFeatures{
viewBinding true
}
-AndroidManifest.xml
<!-- 인터넷 권한 선언 -->
<!-- <manifest> 태그 안에 인터넷 권한 선언하고
<!-- http주소에 대해 강화된 네트워크 보안정책으로 인한 오류 예외처리를 위해 -->
<!-- android:usesCleartextTraffic="true" 설정 -->
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:usesCleartextTraffic="true"
-activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- 이미지뷰, 에디트텍스트, 버튼, 프로그래스바 추가 -->
<ImageView
android:id="@+id/imagePreview"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toTopOf="@+id/editUrl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- 라인을 한줄로 변경하고 개행되지 않게 InputType설정 필수 -->
<EditText
android:id="@+id/editUrl"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:hint="여기에 URL을 입력하세요"
android:maxLines="1"
android:inputType="text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btnDownload"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btnDownload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:backgroundTint="@color/teal_700"
android:text="다운로드"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/imagePreview"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/imagePreview" />
</androidx.constraintlayout.widget.ConstraintLayout>
-MainActivity.kt
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import com.heeyjinny.coroutine.databinding.ActivityMainBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.net.URL
//인터넷 주소를 넣으면 이미지를 불러오는 앱 생성
//1
//인터넷 이미지를 다운로드 하기 위해 인터넷 권한 선언필요
//AndroidManifest.xml 에서 권한 설정
//2
//탑레벨 함수 작성
//suspend키워드를 사용해 코루틴을 만들어 함수 loadImage()생성
//imageUrl을 문자열로 파라미터로 받아 Bitmap형식으로 리턴하는 함수
suspend fun loadImage(imageUrl: String): Bitmap {
//2-1
//파라미터로 전달받은 주소로 URL객체 생성
val url = URL(imageUrl)
//2-2
//URL이 가지고 있는 openStream의 변수 생성
val stream = url.openStream()
//2-3
//주소를 열어 비트맵 이미지 저장한 값을 반환
return BitmapFactory.decodeStream(stream)
}
class MainActivity : AppCompatActivity() {
//뷰바인딩
val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
//3
//다운로드 버튼을 클릭하면 주소를 전달해 이미지를 보여주는 코드 생성
binding.btnDownload.setOnClickListener {
//3-1
//코루틴 스코프 추가,
//디스패처는 Main으로 입력해 UI관련 요소들을 다룰 수 있도록 구성
CoroutineScope(Dispatchers.Main).launch {
//3-2
//버튼이 클릭되면 가장먼저 코루틴 실행
//버튼이 클릭되면 프로그래스바가 화면에 보여지도록 설정
binding.progress.visibility= View.VISIBLE
//3-3
//에디트텍스트에 입력된 값 문자열로 가져와 변수url에 저장
val url = binding.editUrl.text.toString()
//3-4
//loadImage()함수를 호출하면서 url전달
//백그라운드를 처리하는 IO컨텍스트에서 진행되어야함
//withContext()문을 사용해 컨텍스트를 IO로 전환하고 변수bitmap에 저장
val bitmap = withContext(Dispatchers.IO){
loadImage(url)
}
//3-5
//loadImage()함수에서 비트맵 생성하여
//변수bitmap에 저장될 때까지 다음줄이 실행되지않고 멈춤
//이미지뷰에 변수bitmap의 값 입력
binding.imagePreview.setImageBitmap(bitmap)
//3-6
//프로그래스바는 다시 안보이게 설정
binding.progress.visibility = View.GONE
}//코루틴스코프
}//btnDownload
//4
//바인딩 처리를 run스코프로 감싸면 반복되는 binding.을 제거할 수 있음
binding.run {
btnDownload.setOnClickListener {
CoroutineScope(Dispatchers.Main).launch {
progress.visibility= View.VISIBLE
val url = editUrl.text.toString()
val bitmap = withContext(Dispatchers.IO){
loadImage(url)
}
imagePreview.setImageBitmap(bitmap)
progress.visibility = View.GONE
}//코루틴스코프
}//btnDownload
}//바인딩 run
}//onCreate
}//MainActivity
-결과
이 포스팅에 작성한 내용은 고돈호, ⌜이것이 안드로이드다⌟, 한빛미디어(주), 2022 에서 발췌하였습니다.
'Android App > Kotlin' 카테고리의 다른 글
4대 컴포넌트-서비스 실행(스타티드 및 바운드 서비스) (0) | 2022.12.02 |
---|---|
4대 컴포넌트-서비스(Service), 실행방식(스타티드, 바운드, 포어그라운드 서비스) (0) | 2022.12.02 |
스레드의 경량화-코루틴(Coroutine) (1) | 2022.11.29 |
스레드(Thread)-구현하기(타이머 앱) (0) | 2022.11.29 |
스레드(Thread)-루퍼, 핸들러, 메시지 (0) | 2022.11.29 |