MainActivity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package com.example.boostcoursepractice;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView textView;
ImageView imageView;
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sendImageRequest();
}
});
}
public void sendImageRequest() {
String url = "https://lh5.googleusercontent.com/p/AF1QipP88UCg_d5npMcxmBkm_ZXqmxm2korTx5Bdya9k=w237-h160-k-no";
ImageLoadTask task = new ImageLoadTask(url, imageView);
task.execute();
}
}
|
cs |
ImageLoadTask
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
package com.example.boostcoursepractice;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
public class ImageLoadTask extends AsyncTask<Void, Void, Bitmap> {
private String urlStr ;
private ImageView imageView ;
private static HashMap<String, Bitmap> bitmapHash = new HashMap<String, Bitmap>();
public ImageLoadTask(String urlStr, ImageView imageView)
{
this.urlStr = urlStr;
this.imageView = imageView ;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Bitmap doInBackground(Void... voids) {
Bitmap bitmap = null ;
try{
if(bitmapHash.containsKey(urlStr))
{
Log.d("jjh", "해쉬에 있음");
Bitmap oldBitmap = bitmapHash.remove(urlStr);
if(oldBitmap !=null)
{
oldBitmap.recycle();
oldBitmap = null;
}
}
URL url = new URL(urlStr);
bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
bitmapHash.put(urlStr, bitmap);
}catch (Exception e){
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
imageView.setImageBitmap(bitmap);
imageView.invalidate();//다시 그려주는 메서드인데 UI객체는 일부로 할 필요는 없지만 혹시나 해서 해줌
}
}
|
cs |
activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="이미지 가져오기" />
<ImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="100dp"
app:srcCompat="@android:drawable/btn_star_big_on" />
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_light">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18dp" />
</LinearLayout>
</ScrollView>
</LinearLayout>
|
cs |
일단 여기서는 웹에 있는 이미지를 가져오기 위해 그냥 일반적인 스레드 방식으로 비트맵 방식으로 이미지를 가져오고 내부적으로는 핸들러를 이용해서 UI를 바꾸는 방법으로 구현하였다. 중간 코드에 밑에 처럼
if(bitmapHash.containsKey(urlStr))
{
Log.d("jjh", "해쉬에 있음");
Bitmap oldBitmap = bitmapHash.remove(urlStr);
if(oldBitmap !=null)
{
oldBitmap.recycle();
oldBitmap = null;
}
}
URL url = new URL(urlStr);
bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
bitmapHash.put(urlStr, bitmap);
이러한 코드가 있는데 메모리에 비트맵 이미지를 올리고 또 버튼을 클릭하여 이미지를 가지고 올 때 메모리의 이미지가 안사라지고 또 이미지가 올라가는 경우가 생기면 메모리 용량을 많이 차지하는 문제가 생길 수 있으므로(내 생각에는 자바에서 그냥 이미지 비트맵을 가리키는 변수가 없어지기 때문에 자동으로 버릴거 같은데 혹시 모르니까 해주는 거 같다.) url 과 비트맵을 키,값을 가지는 해쉬맵으로 관리하여 쓰였던 url 이면 전에 있던 그 url의 해당하는 비트맵을 recycle즉 없애 주는 코드도 추가하였다.
***************************중요*********************************
1. 자바에서는 HashMap, ArrayList등 이런 컨테이너 인터페이스로 구현해놓은 것들에 원소를 추가 해줄 때 그 대상이 객체이면 객체를 복사하는 것이 아니라 참조자만 가지고 관리한다.(그래서 원래 객체의 값을 변경하면 실제 컨테이너 내부의 객체도 변경된다.)
2.AsyncTask의 onPreExecute, onPostExecute에서도 UI접근이 가능하다. 즉 핸들러큐에 들어간다는 얘기인데 뭔가 onPreExecute에서만 핸드러큐에 들어가서 원래 메인 스레드의 진행을 중지하고 핸들러의 큐를 먼저 실행시켜주는 듯 하다?(이건 확실하지가 않다 지금까지 실험해본 결과로는 onPreExecute가 핸들러 큐에 들어가는 건 확실한데 내 생각에는 본래 진행되던 메인 스레드의 진행이 다 끝나고 진행되어야 하는데 갑자기 핸들러가 진행된다. 아직 의문이다 이건 언젠가 아는날이 오지 않을까...?)
'2019 summer 부스트코스 에이스(안드로이드 프로그래밍) > 5. 네트워킹' 카테고리의 다른 글
5-5-1 JSON 이해하기 / 5-5-1 Gson 사용하기 (0) | 2019.08.17 |
---|---|
5-4-1 Volley 사용하기 (0) | 2019.08.17 |
5-3-2 웹으로 요청하기 (0) | 2019.08.17 |
5-2-1 소켓 사용하기 (0) | 2019.08.15 |
5-1-1 스레드 사용하기 / 5-1-2 AsyncTask 사용하기 (0) | 2019.08.15 |