본문 바로가기
수업내용

20230725 Android

by titlejjk 2023. 7. 25.

어제배운 수업의 목적은 서버가 응답한 JSON형식의 문자열에서 Data를 추출해낸 것이다

 

오늘은 기존에 만들어두었던 스프링 프레임워크에 있는 코드를 이용해 OracleDB에 있는 gallery테이블을 출력해보겠다.

 

먼저 새로운 모듈은 만들어주고 아래와 같이 설정해준다.

 

.인터넷 연결은 위한 AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Setp04gallery"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

Layout에 ListView추가

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">

    <ListView
        android:id="@+id/listView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="1dp"
        android:layout_marginTop="1dp"
        android:layout_marginEnd="1dp"
        android:layout_marginBottom="1dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

글을 눌렀을 때 detail에 사용할 Layout 추가

 

이런 식으로 만들예정이다.

 

 

<?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="200dp"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="180dp"
        android:layout_height="match_parent"
        android:layout_margin="10dp" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_gravity="bottom"
        android:layout_margin="10dp"
        android:layout_weight="1"
        android:orientation="vertical">

        <TextView
            android:id="@+id/writer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="작성자:김구라"
            android:textSize="20sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/caption"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="1"
            android:text="어쩌구 저쩌구...."
            android:textSize="18sp"
            android:textStyle="italic" />

        <TextView
            android:id="@+id/regdate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="2023.03.07 13:00"
            android:textSize="18sp"
            android:textStyle="bold" />
    </LinearLayout>
</LinearLayout>

 

그런다음 GarlleryAdapter Class를 만들어 Custom Adapter를 만들어준다.

 

package com.example.setp04gallery;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

public class GalleryAdapter extends BaseAdapter {

    @Override
    public int getCount() {
        return 0;
    }

    @Override
    public Object getItem(int i) {
        return null;
    }

    @Override
    public long getItemId(int i) {
        return 0;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        return null;
    }
}

 

 

그런다음 GallerDto를 만들어서 기본생성자와 필드 Getter/Setter도 만들어준다.

 

package com.example.setp04gallery;

public class GalleryDto {
    private int num;
    private String writer;
    private String caption;
    private String imagePath;
    private String regdate;

    public GalleryDto(){}

    public GalleryDto(int num, String writer, String caption, String imagePath, String regdate) {
        this.num = num;
        this.writer = writer;
        this.caption = caption;
        this.imagePath = imagePath;
        this.regdate = regdate;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getWriter() {
        return writer;
    }

    public void setWriter(String writer) {
        this.writer = writer;
    }

    public String getCaption() {
        return caption;
    }

    public void setCaption(String caption) {
        this.caption = caption;
    }

    public String getImagePath() {
        return imagePath;
    }

    public void setImagePath(String imagePath) {
        this.imagePath = imagePath;
    }

    public String getRegdate() {
        return regdate;
    }

    public void setRegdate(String regdate) {
        this.regdate = regdate;
    }
}

 

여기까지 준비해준 후에 생성자의 인자로 받을 예정인 필요한 필드를 정의해준다.

package com.example.setp04gallery;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import java.util.List;

public class GalleryAdapter extends BaseAdapter {
    //필요한 필드 정의하기
    private LayoutInflater inflater; //레이아웃 전개자 객체를 담을 필드
    private Context context; //앱 컨테그트를 담을 필드
    private int layoutRes; //셀의 레이아웃 리소스 id를 담을 필드
    private List<GalleryDto> list; //모델

    public GalleryAdapter(Context context, int layoutRes, List<GalleryDto> list) {
        this.context = context;
        this.layoutRes = layoutRes;
        this.list = list;
        //레이아웃 전개자 객체의 참조값을 얻어내서 필드에 저장
        inflater=LayoutInflater.from(context);

    }

    @Override
    public int getCount() {
        return 0;
    }

    @Override
    public Object getItem(int i) {
        return null;
    }

    @Override
    public long getItemId(int i) {
        return 0;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        return null;
    }


}

 

레아웃전개자 => 레이아웃을 전개해서 view를 만들어주는 것이 LayoutInflater이다.

LayoutInflater를 통해 .from메서드에 context를 담아서 inflater에 담아준다.

 

getCount()는 list.size를 return => 모델의 갯수

getItem(int i)는 view의 i번째 모델의 item을 가져온다 => i번째 모델

getItemId(int i)는 list.get(i).getNum()을 return => i번째 모델의 id(Primary key)가 있으면 그 값을 return

getView(int i, View view, ViewGroup viewGrop) => i번째 cell의 View를 만들거나 수정해서 return

 

문자열 데이터는 JSON으로 받는다 데이터의 용량이작아 상관없지만

Image의 경우는 다르다 Image관련해서 JSON으로 받을 수 있는 것은 Image의 경로뿐이다.

Image View를 조금더 빠르게 비동기로 처리하기 위해 라이브러리를 사용할 것 이다.

라이브러리 이름은

Glide

는 라이브러리이다. 이 라이브러리를 이용해 Image를 불러올것이다.

예전 같은 경우에는(maven사용)시 xml에 dependency를 이용해 주었지만 gradle은 간단하게 가능하다.

 

해당 라이브러리에 

 

를 추가해주었다.

 

그런다음 Glide라이버리를 사용한 메서드를 완성시켜준다.

 

package com.example.step04gallery;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.util.List;

public class GalleryAdapter extends BaseAdapter {
    //필요한 필드 정의하기
    private LayoutInflater inflater; //레이아웃 전개자 객체를 담을 필드
    private Context context; //앱 컨테그트를 담을 필드
    private int layoutRes; //셀의 레이아웃 리소스 id를 담을 필드
    private List<GalleryDto> list; //모델

    public GalleryAdapter(Context context, int layoutRes, List<GalleryDto> list) {
        this.context = context;
        this.layoutRes = layoutRes;
        this.list = list;
        //레이아웃 전개자 객체의 참조값을 얻어내서 필드에 저장
        inflater=LayoutInflater.from(context);

    }
    //모델의 갯수
    @Override
    public int getCount() {
        return list.size();
    }
    //i번째 모델
    @Override
    public Object getItem(int i) {
        return list.get(i);
    }
    //i번째 모델의 아이디(primary key)가 있으면 return
    @Override
    public long getItemId(int i) {
        return list.get(i).getNum();
    }
    //i번째 cell의 View를 만들거나 수정해서 return
    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {
        if(convertView == null){
            //레이아웃 전개자 객체를 이용해서
            convertView=inflater.inflate(layoutRes, viewGroup, false);
        }
        // position 에 해당하는 GalleryDto 를 얻어내서
        GalleryDto dto=list.get(position);
        ImageView imageView=convertView.findViewById(R.id.imageView);
        TextView textWriter=convertView.findViewById(R.id.writer);
        TextView textCaption=convertView.findViewById(R.id.caption);
        TextView textRegdate=convertView.findViewById(R.id.regdate);
        //TextView에는 작성자, 제목, 등록일을 출력하고
        textWriter.setText(dto.getWriter());
        textCaption.setText(dto.getCaption());
        textRegdate.setText(dto.getRegdate());
        //ImageView에는 Glide를 이용해서 이미지를 출력하기
        Glide.with(context)
                .load(dto.getImagePath())
                .centerCrop()
                .placeholder(R.drawable.ic_launcher_background)
                .into(imageView);
        //gallery정보가 출력된 View객체 리턴해주기
        return convertView;
    }


}

 

그런다음 스프링프레임워크로 들어와서 AndroidController에 아래와 같이 메서드를 추가해준다.

 

@Autowired
	private GalleryDao galleryDao;
	
	@GetMapping("/android/gallery/list")
	public List<GalleryDto>galleryList(){
		//20개만 select해 오도록 GalleryDto에 정보 담기
		GalleryDto dto = new GalleryDto();
		dto.setStartRowNum(1);
		dto.setEndRowNum(20);
		//GalleryDao객체가 리턴해주는 데이터를 바로 리턴해주기
		return galleryDao.getList(dto);
	}

 

다시 AndroidStudio로 돌아와 MainActivity Class에 아래와 같이 코드를 완성시켜준다.

Util객체를 사용하기 위해 gallery에 Util Class를 복사해준 후 추상메서드를 받아준다.

아이템은 없지만 데이터타입 List<GalleryDto>list의 빈모델을 만들어서 스프링에서 가져온 JSON을 list에 넣어주고 ListView에 넣어서 목록을 보이게끔 완성시켜준다.

    @Override
    public void onSuccess(int requestId, Map<String, Object> result) {
        if(requestId==0){
            //Map 에는 "data" 라는 키값으로 [{}, {}, {}] 형식의 json 문자열이 들어 있다.
            String json = (String) result.get("data");
            try {
                JSONArray arr = new JSONArray(json);
                //반복문 돌면서 JSONObject 객체를 하나씩 얻어낸다.
                for(int i=0; i<arr.length(); i++){
                    JSONObject tmp = arr.getJSONObject(i);
                    //JSONObject 안에 있는 정보를 추출해서 GalleryDto 에 담는다.
                    GalleryDto dto = new GalleryDto();
                    dto.setNum(tmp.getInt("num"));
                    dto.setWriter(tmp.getString("writer"));
                    dto.setCaption(tmp.getString("caption"));
                    String url = "http://192.168.0.31:9000/boot07/gallery/images/"+tmp.getString("imagePath");
                    dto.setImagePath(url);
                    //GalleryDto 를 list 에 누적시킨다.
                    list.add(dto);
                }
                //모델이 업데이트 되었다고 어댑터에 알려서 ListView 가 업데이트 되도록 한다.
                adapter.notifyDataSetChanged();
            } catch (JSONException e) {
                throw new RuntimeException(e);
            }
        }
    }

 

이렇게 완성시켜주면

 

짜잔

'수업내용' 카테고리의 다른 글

20230726 Kotlin  (0) 2023.07.26
20230725 Android 다른화면으로 넘어가기  (0) 2023.07.25
20230724 Android HttpRequest2  (0) 2023.07.24
20230721 Android HttpRequest  (0) 2023.07.21
20230721 Android CustomAdapter 2  (0) 2023.07.21

댓글