본문 바로가기
Android/Concepts

서버로부터 Bitmap 이미지 받아오기

by JuHy_ 2020. 4. 27.

HttpURLConnection이나 Volley 라이브러리를 이용하여 http 통신으로 서버로부터 데이터를 받아올 수 있다.

하지만 이미지의 경우 용량이 크기 때문에 다른 데이터와 구분하여 다른 방식으로 받는 것이 효율적이다.

따라서 이미지를 별도의 url로 전달받아 해당 url을 통해 별도로 다운로드하여 사용하게 된다. 

 

요즘에는 이미지 파일을 다운로드 할 때 여러가지 편리한 기능을 제공하는 라이브러리들을 사용한다.

UniversalImageLoader 나 Glide 라이브러리를 사용하면 다운로드 및 캐싱까지 자동으로 처리해준다.

 

하지만 이 글에서는 기본적으로 제공되는 URL의 openConnection을 이용하여 직접 이미지를 다운로드하여,

BitmapFactory를 이용하여 Bitmap으로 변환하고, HashMap을 통해 직접 캐싱하는 방법을 알아보도록 한다.

 

Source Code

먼저 서버로부터 다운로드해야 하므로 메인 쓰레드가 아닌 AsyncTask로 분리하여 구현하였다.

AsyncTask에 대한 설명은 아래 글을 참고.

https://ju-hy.tistory.com/63

 

AsyncTask 사용법

AsyncTask란? Thread를 사용할 때는 UI 객체에 접근하기 위해서는 Handler를 통해 접근해야 한다. 하지만 AsyncTask를 사용하면 하나의 클래스 안에 Thread 동작 부분과 UI 접근 부분을 동시에 정의할 수 있다. 따..

ju-hy.tistory.com

 

package com.juhy.myapplication;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;

import java.net.URL;
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 {
            // 이미 url을 통해 불러온 적이 있다면 이전 bitmap을 삭제
            if(bitmapHash.containsKey(urlStr)) {
                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();
    }

}

ImageLoadTask()

생성자에서는 액티비티로부터 이미지를 받아올 url과 이미지를 띄울 ImageView를 받아오도록 한다.

 

doInBackground()

HashMap에 url을 key로 한 bitmap이 있다면 recycle()로 없앤다.

url로 서버와 연결한 뒤 InputStream을 BitmapFactory로 decode하여 bitmap 변수에 저장한다.

새 bitmap을 HashMap에 저장한다.

 

onPostExecute()

ImageView에 bitmap 이미지를 넣어준 뒤 최신화한다.

 

package com.juhy.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = findViewById(R.id.imageView);

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendImageRequest();
            }
        });
    }

    public void sendImageRequest(){
        String url = "https://movie-phinf.pstatic.net/20161123_188/1479862185516tYkKO_JPEG/movie_image.jpg";
        ImageLoadTask task = new ImageLoadTask(url, imageView);
        task.execute();
    }

}

MainActivity에서는 이미지를 받아올 AsyncTask에 url과 imageView를 넘겨준 뒤 실행해준다.

 

버튼 클릭 시 url로부터 정상적으로 이미지를 받아와 ImageView에 띄워주는 것을 볼 수 있다.

 

 

Reference

[부스트코스]안드로이드 프로그래밍

https://www.edwith.org/boostcourse-android

'Android > Concepts' 카테고리의 다른 글

SQLite DB에 데이터 저장하기  (0) 2020.05.01
Glide 라이브러리 사용법  (0) 2020.04.30
Gson을 이용하여 Json 파싱하기  (0) 2020.04.27
Volley 라이브러리 사용법  (0) 2020.04.26
HttpURLConnection을 이용한 HTTP 통신  (0) 2020.04.25