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가 핸들러 큐에 들어가는 건 확실한데 내 생각에는 본래 진행되던 메인 스레드의 진행이 다 끝나고 진행되어야 하는데 갑자기 핸들러가 진행된다. 아직 의문이다 이건 언젠가 아는날이 오지 않을까...?)

 

 

결과화면

 

+ Recent posts