Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Week8 thread handler looper #4

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/ktlint.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
compileSdk 32

defaultConfig {
applicationId "com.example.coroutine"
minSdk 21
applicationId "com.lee989898.myapplication"
minSdk 26
targetSdk 32
versionCode 1
versionName "1.0"
Expand All @@ -29,14 +29,17 @@ android {
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
dataBinding true
}
}

dependencies {

implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.6.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.coroutine
package com.lee989898.myapplication

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
Expand All @@ -19,6 +19,6 @@ class ExampleInstrumentedTest {
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.coroutine", appContext.packageName)
assertEquals("com.lee989898.myapplication", appContext.packageName)
}
}
7 changes: 5 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.coroutine">
package="com.lee989898.myapplication">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 퍼미션은 어디에서 사용하는건가요??

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미지 url로 가져올때 사용하고 있습니다!!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

glide로 이미지를 로드하신다면 INTERNET 권한만 있어도 충분하지 않나요?!


<application
android:allowBackup="true"
Expand All @@ -11,7 +14,7 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Coroutine"
android:theme="@style/Theme.MyApplication"
tools:targetApi="31">
<activity
android:name=".MainActivity"
Expand Down
11 changes: 0 additions & 11 deletions app/src/main/java/com/example/coroutine/MainActivity.kt

This file was deleted.

34 changes: 34 additions & 0 deletions app/src/main/java/com/lee989898/myapplication/ConvertBitMap.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.lee989898.myapplication

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Base64
import java.io.ByteArrayOutputStream

class ConvertBitMap {
fun BitmapToString(bitmap: Bitmap): String {
val baos =
ByteArrayOutputStream() //바이트 배열을 차례대로 읽어 들이기위한 ByteArrayOutputStream클래스 선언, 차례대로 받지 않으면 어떤 일이 일어날까요?
bitmap.compress(Bitmap.CompressFormat.PNG, 70, baos) //bitmap을 압축 (숫자 70은 70%로 압축한다는 뜻, 몇으로 해야 좋은지는 잘 모르겠음)
val bytes = baos.toByteArray() //해당 bitmap을 byte배열로 바꿔준다.
return Base64.encodeToString(bytes, Base64.DEFAULT) //Base 64 방식으로byte 배열을 String으로 변환
}

fun StringToBitmap(encodedString: String?): Bitmap? {
return try {
val encodeByte: ByteArray = Base64.decode(
encodedString,
Base64.DEFAULT
) // String 화 된 이미지를 base64방식으로 인코딩하여 byte배열을 만듬
BitmapFactory.decodeByteArray(
encodeByte,
0,
encodeByte.size
) //byte배열을 bitmapfactory 메소드를 이용하여 비트맵으로 바꿔준다.
//만들어진 bitmap을 return
} catch (e: Exception) {
e.message
null // 안되면 어쩔 수 없이 null 보내야죵.. res에서 placeholder같은거 하나 보내도 좋을듯
}
}
}
110 changes: 110 additions & 0 deletions app/src/main/java/com/lee989898/myapplication/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.lee989898.myapplication

import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.*
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.lee989898.myapplication.databinding.ActivityMainBinding
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URL

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding
private lateinit var myHandler: Handler
var count = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var count = 0
private var count = 0


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
myHandler = MyHandler()
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

binding.btn1.setOnClickListener {
BackgroundThread1().start()
}
binding.btn2.setOnClickListener {
BackgroundThread2().start()
}
binding.img.setOnClickListener {
BackgroundThread3().start()
}
}

@SuppressLint("HandlerLeak")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 어노테이션은 왜 사용하신건가요??

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 궁금해서 찾아봤는데 핸들러 클래스가 외부 클래스에 대한 참조를 유지하지 않도록 한다고 하네요! inner class를 사용하셨기 때문에 ide에서 해당 어노테이션 추가를 제안했나봅니다~ 추후 inner class -> nested class로 변경해보시는 것도 추천합니다 :)

inner class MyHandler : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
// 다른 Thread에서 전달받은 Message 처리
val getBundle = msg.data
val img = getBundle.getString("image")
img.let {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 let 블록은 없어도 될 것 같은데요?!

binding.img.post {
binding.img.setImageBitmap(ConvertBitMap().StringToBitmap(it))
}
Comment on lines +44 to +46
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋슴다~!!

Comment on lines +44 to +46
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서도 마찬가지지만 왜 post를 쓰신건가요?!

}
binding.count.text = getBundle.getInt("count").toString()
}
}

inner class BackgroundThread1 : Thread() {
override fun run() {
//implement Image 1
val minho = getBitmapFromURL("https://avatars.githubusercontent.com/u/15981307?v=4")
val bundle = Bundle()
bundle.putString("image", minho?.let { ConvertBitMap().BitmapToString(minho) })
val msg = myHandler.obtainMessage()
with(msg) {
data = bundle
SystemClock.sleep(2000)
myHandler.sendMessage(this)
}
}
}
inner class BackgroundThread2 : Thread() {
override fun run() {
//implement Image 2
val joonKyung = getBitmapFromURL("https://avatars.githubusercontent.com/u/15981307?v=4")
val bundle = Bundle()
bundle.putString("image", joonKyung?.let { ConvertBitMap().BitmapToString(joonKyung) })
val msg = myHandler.obtainMessage()
with(msg) {
data = bundle
SystemClock.sleep(2000)
myHandler.sendMessage(this)
}
}
}
inner class BackgroundThread3 : Thread() {
override fun run() {
//implement Count
while (isAlive) {
val bundle = Bundle()
val msg = myHandler.obtainMessage()
count++
bundle.putInt("count", count)
with(msg) {
data = bundle
SystemClock.sleep(1000)
myHandler.sendMessage(this)
}
}
}
Comment on lines +80 to +94
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여러번 눌렀을 때 처리도 해주시면 좋을 것 같습니다~!!

}

private fun getBitmapFromURL(src: String): Bitmap? {
return try {
val url = URL(src)
val connection: HttpURLConnection = url.openConnection() as HttpURLConnection
connection.doInput= true //읽기모드임
connection.connect()
val input: InputStream = connection.inputStream
BitmapFactory.decodeStream(input)
} catch (e: IOException) {
e.printStackTrace()
null
}
}
}
67 changes: 51 additions & 16 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,18 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<layout 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">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
xmlns:tools="http://schemas.android.com/tools">

<data>

</data>
Comment on lines +6 to +8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 태그는 사용안하시는거면 지워도 될 것 같습니다~!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 지우겠습니다!


<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<ImageView
android:id="@+id/img"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/img" />

<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:text="버튼1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/count" />

<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="20dp"
android:text="버튼2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/count" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
2 changes: 1 addition & 1 deletion app/src/main/res/values-night/themes.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Coroutine" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<resources>
<string name="app_name">Coroutine</string>
<string name="app_name">My Application</string>
</resources>
2 changes: 1 addition & 1 deletion app/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Coroutine" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.coroutine
package com.lee989898.myapplication

import org.junit.Test

Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.2.0' apply false
id 'com.android.library' version '7.2.0' apply false
id 'com.android.application' version '7.2.1' apply false
id 'com.android.library' version '7.2.1' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}

Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#Thu May 19 14:25:12 KST 2022
#Fri Aug 12 14:08:08 KST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionPath=wrapper/dists
Expand Down
2 changes: 1 addition & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ dependencyResolutionManagement {
mavenCentral()
}
}
rootProject.name = "Coroutine"
rootProject.name = "My Application"
include ':app'