본문 바로가기
안드로이드

[Android] 5. 네트워킹 - 이미지 다운로드

qbang 2019. 7. 29.

안녕하세요 이번 시간에는 5강 네트워킹의 여섯번째 강의인 '이미지 다운로드' 리뷰입니다.

해당 리뷰는 2019/07/29 - [BOOSTER 안드로이드] - 5. 네트워킹 - JSON 이해하기 와 이어집니다.

코드가 이어져서 작성되니 꼭 참고해주세요!

마찬가지로 개념을 알아보면서 실습한 내용을 덧붙여 알아보도록 하겠습니다!

 


저번 시간에는 웹서버에 데이터를 요청하고 응답을 받아 처리하는 과정을 해봤는데요, 응답으로 받을 데이터가 이미지 파일인 경우에는 조금 다른 방식으로 처리합니다.

왜냐하면 이미지 파일 하나의 크기가 커지면서 이미지 파일을 다른 데이터와 구분하여 받는 방식이 더 효율적이게 되었기 때문입니다.

UniversalImageLoader와 같은 외부 라이브러리는 간단하게 이미지를 다운로드할 수 있도록 도와주지만, 이번 강의에서는 직접 이미지를 다운로드하는 코드를 작성합니다.

변경사항이 있는 파일만 추가를 해놓았습니다. 다른 파일은 이전 글에서 확인해주세요!

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:layout_height="match_parent">

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="요청하기" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="이미지 가져오기" />

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="203dp"
            android:layout_height="226dp" />

    </LinearLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FFEB3B">

        <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="18sp" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>

 

ImageLoadTask.java

package com.example.myvolley;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.Image;
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;
    //HashMap 객체를 만들고 이미지의 주소를 메모리에 만들어진 비트맵 객체와 매핑
    private static HashMap<String, Bitmap> bitmapHashMap = 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(bitmapHashMap.containsKey(urlStr)){
               Bitmap oldBitmap = bitmapHashMap.remove(urlStr);
               if(oldBitmap != null){
                   oldBitmap.recycle();
                   oldBitmap = null;
               }
            }
            URL url = new URL(urlStr);
            bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());

            bitmapHashMap.put(urlStr, bitmap);
        }catch (Exception e){
            e.printStackTrace();
        }
        //여기서 return 하면 onPostExcute에 넘어감
        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();
    }
}

 

MainActivity.java

package com.example.myvolley;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;

import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity {
    TextView textView;
    ImageView imageView;

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

        textView = (TextView) findViewById(R.id.textView);
        imageView = (ImageView) findViewById(R.id.imageView);

        //이미지뷰 처리
        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view){
                sendImageRequest();
            }
        });

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

        if(AppHelper.requestQueue == null) {
            AppHelper.requestQueue = Volley.newRequestQueue(getApplicationContext());
        }

    }

    public void sendImageRequest(){
        String url = "https://scontent-iad3-1.cdninstagram.com/vp/aebcb66408f68ef6f3c50dc6f584e1c7/5DD2C69D/t51.2885-15/e35/29737938_1939536756120090_6620432602039844864_n.jpg?_nc_ht=scontent-iad3-1.cdninstagram.com";

        ImageLoadTask task = new ImageLoadTask(url, imageView);
        task.execute();
    }

    public void println(String data){
        textView.append(data + "\n");
    }

    public void sendRequest(){
        String url = "http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=430156241533f1d058c603178cc3ca0e&targetDt=20120101";
        StringRequest request = new StringRequest(
                //요청방식 지정
                Request.Method.GET,
                //웹서버의 url 정보를 전달
                url,
                //응답을 성공적으로 받았을 때 이 리스너의 onResponse 메소드를 자동으로 호출해주는 리스너 객체
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        println("응답 -> "+response);

                        processResponse(response);
                    }
                },
                //에러가 발생했을 때 호출될 리스너 객체
                new Response.ErrorListener(){
                    @Override
                    public void onErrorResponse(VolleyError error){
                        println("에러 -> "+error.getMessage());
                    }
                }
            ){ //POST 방식으로 파라미터를 넣음 -> request 객체안에 메소드를 재정의


            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String,String> params = new HashMap<String, String>();

                return params;
            }
        };

        //매번 받은 새로운 결과를 출력
        request.setShouldCache(false);
        AppHelper.requestQueue.add(request);
        println("요청 보냄");
        }

        public void processResponse(String response){
        //자바 객체로 변환
            Gson gson = new Gson();
            MovieList movieList = gson.fromJson(response, MovieList.class);

            if(movieList != null){
                int countMovie = movieList.boxOfficeResult.dailyBoxOfficeList.size();
                println("박스오피스 타입: "+movieList.boxOfficeResult.boxofficeType);
                println("응답받은 영화 갯수: "+countMovie);
            }
        }
   }

위 코드에 대한 결과는 아래와 같습니다.

 

초기 화면
결과 화면(이미지 출처: https://www.twgram.me/media/1751865776047936402)

bitmap 객체를 사용하여 이미지를 가져와 이미지뷰에 표시하였습니다.

 

글 읽어주셔서 감사합니다 :)

댓글