위 와 같이 msa 환경에서 많은 네트워크 IO가 일어나게 되었고 이 때 해당 스레드는 blocking 상태가 되어 전체적인 서버 측면에서 보았을 때 스레드 풀안에 한정된 스레드 안에서 많은 스레드가 놀게 되고 cpu도 낭비되고 있어 많은 request가 들어왔을 때 레이턴시가 늘어나게 된다.

 

 

톰캣 맥스 스레드를 1로 제한 100개의 요청스레드 동시에 요청 테스트 -> 서블릿 스레드가 max=1 로 잡혀 있기 때문에 스레드가 늘어나지 않고 해당 1개의 스레드로 작업이 진행됨

 

 

 

2초가 걸리는 외부 API를 호출 했을 때 호출한 서버의 해당 스레드는 2초의 blocking이 걸리게 된다. 여기서는 호출한 서버의 톰캣 스레드가 1이기 때문에 계속 2초씩 blocking이 걸리게 되고 2초의 하나씩 하나의 작업을 처리하게 됨

스프링 4.0 부터 나온 AsyncRestTemplate을 사용하게되면 async 형태로 호출하게 되서 레이턴시는 줄었지만, 스레드가 늘어났다.

서블릿 스레드는 1개로 유지 된다. 하지만 AsyncRestTemplate 자체가 워크 스레드를 만들게 되고 그 스레드가 blocking에 걸리게 된 것이다.

 



이와 같이 AsyncRestTemplate에 Netty4ClinetHttpRequestFactory(New NioEventLoopGrop(1)) 네티 라이브러리를 이용하면

nonblocking + async 처리를 할 수 있고 위와 같이 스레드 개수가 늘어나지 않는다라는 걸 알 수 있다.

 

만약 받은 데이터를 맵핑하거나 다른 처리를 하고 싶다면

위와 같이 콜백 함수를 등록하고 DefferdResult에 설정해주면 된다.

 

한번 가져온 데이터 응답을 가지고 다른 api로 넘겨줘서 2번호출 할 때 위와 같이 콜백을 두번 등록

2번 api콜을 통해 가져온 데이터를 어플리케이션 스레들 풀에서 비동기로 한번 더 작업을 하기 위해 다시 콜백등록

 

 

이런식으로 계속 콜백의 콜백을 등록하는 형식으로 데이터를 제어 할 수 있음 하지만 코드가 깔끔하지 않다 어떻게 해결할까?

이름 붙인 인자 : 함수를 호출할 때는 함수에 전달하는 인자 중 일부의(또는 전부)의 이름을 명시할 수 있다.

1
joinToString(list, separator = "; ", prefix = "(", postfix = ")")
cs

디폴트 파라미터 값

1
2
3
4
5
6
fun <T> joinToString(
    collection: Collection<T>,
    separator: String = ", ",
    prefix: String = "",
    postfix: String = ""
)
cs

설정 시

1
2
3
joinToString(list, ", """"")
joinToString(list)
joinToString(list, ", ")
cs
 
위와 같이 함수 호출 가능

 

그러나 java에서 코틀린의 디폴트 파라미터 값을 가진 함수를 호출 할 때는 적용이 안된다

이를 해결하기 위해

1
2
3
4
5
6
7
@JvmOverloads
fun <T> joinToString(
    collection: Collection<T>,
    separator: String = ", ",
    prefix: String = "",
    postfix: String = ""
)
cs

해당 함수에 @JvmOverloads를 붙이면

1
2
3
String joinToString(Collection collection, String separator, String prefix, String postfix)
String joinToString(Collection collection, String separator, String prefix)
String joinToString(Collection collection, String separator)
cs

위같은 형태로 생성자가 자동으로 생성되어 자바에서도 코틀린의 디폴트 파라미터와 비슷한 형태로 사용할 수 있다.


최상위 함수

 

다음과 같이 join.kt라는 소스파일을 만들고 최상위 함수를 만들면 (class가 있는 경우 class 밖에 작성)

package strings

fun joinToString(...): String {...}​

 

컴파일 할 경우 아래와 같이 직전에 생성 한 <join.kt> 소스 파일의 이름과 같은 자바의 class가 생성되고 그 안에 static 메서드가 생성고
package strings;

public class JoinKt {
  public static String joinToString(...) {...}
}

 

이를 사용하기 위해서는 코틀린에서는 패키지만 import 시키면 되고 자바에서는 패키지.클래스를 import 시켜줘야함

 

만약 클래스 이름을 바꾸고 싶다면

@file:JvmName("StringFunctions")
package strings
fun joinToString(...): String {...}

 

이와 같이 패키지 선언 전에 @file:JvmName 어노테이션에 변경하고 싶은 클래스의 이름을 지정하면 된다.

 

 

다음과 같이 최상위단에 프로퍼티를 선언할 수 도 있다.

val AA  = "aa"

var bb = "bb"

 

이렇게 선언 시

public final class JoinKt {
  
   private static final String AA = "aa";
   
   private static String bb = "bb";

   public static final String getAA() {
      return AA;
   }

   public static final String getBb() { return BB; }

   public static final void setBb(String bb) { this.BB = bb }
}

이렇게 private static final 로 멤버변수가 생성되고 만약 아래와 같이 const val을 붙이면

const val AA  = "aa"
public final class JoinKt {
  
   public static final String AA = "aa";
}

getter 없이 public static final 로 생성된다.

 

 


확장함수

 

다음과 같이 선언할 수 있고 확장한 수신객체에 마치 멤버변수가 추가된 것처럼 사용할 수 있다.

package strings

fun String.lastChar() : Char = this.get(length - 1)
println("kotlin".lastChar())

 

 

여기서 String은 수신객체타입, this를 수신객체라고 명칭한다.

 

확장함수를 사용할 때 import를 해야한다

import strings.lastChar 메서드명 까지 하거나 import strings.* 이렇게 전체도 가능하다.

한 파일안에서 다른 여러 패키지에 속해있는 이름이 같은 함수를 가져와야 할 경우

import strings.lastChar as last

val c = "Kotlin".last()

이렇게 as 키워드를 통해 확장함수 명칭을 다르게 사용해야한다.

 

이렇게 생성된 확장함수는 결국 자바의 static변수로 컴파일된다.

/* 자바 */

char c = StringUtilKt.lastChar("Java");

 

 

import strings.lastChar는 오버라이드할 수 없다.

정적 메서드 이기 때문에 오버라이드 불가

 

note! : 어떤 수신객체의 멤버 함수와 확장함수의 이름과 시그니처가 같다면 멤버변수가 우선적으로 호출

그래서 어떤 멤버변수를 추가 할 때 기존에 같은 이름과 시그니처를 가지고 있던 확장함수를 쓰던 부분이 전부 멤버변수를 호출하도록 바뀌기 때문에 주의해야 한다.

 

확장 프로퍼티

var StringBuilder.lastChar: Char
	get() = get(length - 1)
	set(value: Char) {
    	this.setCharAt(length - 1, value)
	}

get 정의 필수

 

 

 

 

 

 

  • 한국 타임존 변경
    • 기존 서버 설정 시간 삭제 : sudo rm /etc/localtime
    • 아시아 존으로 서버 시간 설정 : sudo ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime
    • 정상 설정 확인 : date
  • hostname 변경
    • name 변경 : sudo hostnamectl set-hostname testname
    • hosts 변경 : sudo vi /etc/hosts 

만약 필드가(여기서는 예로 GD_SALE_ENDDT로 하겠다) varchar로 되어있는데 날짜형식으로 데이터를 저장하고 있다면

select의 경우 다음과 같이

update t_goods set WEIGHT=54, UPDATE_DT=UPDATE_DT where GD_SALE_ENDDT > CURRENT_TIMESTAMP()

로 해도 자동으로 현재시간이 varchar로 형변환 되서 비교하게 된다.

 

 

 

하지만 update의 경우

select wid, GD_SEQ, GD_NAME, WEIGHT, GD_SALE_ENDDT, UPDATE_DT from t_goods where GD_SALE_ENDDT > CURRENT_TIMESTAMP() 

이러식으로 하면

Data truncation: Truncated incorrect datetime value 이런 오류가 발생한다. 따라서

update t_goods set WEIGHT=54, UPDATE_DT=UPDATE_DT where GD_SALE_ENDDT > DATE_FORMAT(CURRENT_TIMESTAMP(), '%Y%m%d%H%i%s');

와 같이 DATA_FORMAT을 이용하여 명시적으로 형변환을 해줘야 오류없이 비교가 된다.

 

 

 

*보통 날짜 포맷에서

MM(월) mm(분) 으로 월과 분을 구별하는데

쿼리문에서는 %m(월), %i(분)로 구별한다.

git clone https://github.com/libgit2/libgit2 MyProject

해당 주소의 깃 저장소를 자신의 로컬의 MyProject라는 디렉토리를 만들고 거기에 복제한다.

 

git commit -a

Tracked상태의 모든 파일을 Staging Area로 자동으로 올리고 commit한다.(Untracked상태는 안됨) 

example) git commit -a -m "message"

 

git log -p

commit log를 diff의 내용도 포함해서 보여준다.

 

git log --all

모든 브랜치에 대해서 커밋 로그를 보여준다.

 

git log --oneline


commit log를 간략히 한 줄로 보여준다.

 

git log --pretty=format:"%h - %an, %ar : %s"

commit log를 지정한 format형식으로 보여준다.

result)

ca82a6d - Scott Chacon, 6 years ago : changed the version number

085bb3b - Scott Chacon, 6 years ago : removed unnecessary test

a11bef0 - Scott Chacon, 6 years ago : first commit

 

git log --author SearchName

 

저자의 이름이 SearchName을 포함하고 있는 commit log만 보여준다.

 

git log --grep SerachWord

commit message에 SearchWord를 포함 하는 log만 보여준다.  

 

git log -S SearchCode​

코드의 변경사항에 SearchCode를 포함하고 있는 commit log만 보여준다.

 

git log -- path1 path2​

변경된 파일이 path1 또는 path2를 포함하고 있는 commit log만 보여준다.

 

git commit --amend​

Staging Area에 있는 내용을 추가하여 마지막 커밋을 수정한다.(커밋 메세지도 수정 가능)

 

git remote -v​

원격 저장소의 단축이름과 주소를 보여준다.

 

git remote add A RemoteAddress

RomoteAddress의 원격 저장소를 A라는 이름으로 추가한다.

 

git fetch [remote-name]

remote-name의 원격 저장소에 있는 데이터를 가져온다. 자동으로 Merge하지 않는다.

 

git push origin master

master브랜치를  origin이라는 이름을 가진 원격 저장소에 Push한다. 단 원격 저장소에 현재 자신의 로컬상태 이후로 Push한 사람이 없어야 가능하다.

 

git remote show [remote-name]

해당 원격저장소의 URL과 추적하는 브랜치를 출력한다.

 

git tag -a [tag-name] -m [tag-message]​

해당 이름과 해당 메세지로 Annotated 태그를 만든다.

 

git tag [tag-name]

해당 이름으로 Lightweight 태그를 만든다.

 

git push [remote-name] [tag-name]

해당 원격저장소에 해당 태그를 푸시한다.(git push 명령어로는 태그를 push하지 않음)

 

git push [remote-name] --tags

로컬에 있는 모든 태그(들)을 푸시한다.

 

git checkout -b [branch-name] [tag-name]​

해당 tag에서 해당 이름으로 새로운 브랜치를 생성한다.

 

git branch -d [branch-name]

해당 브랜치를 삭제한다.

git push [remote-name] :[remote-branch-name]

해당 원격 저장소의 해당 브랜치를 삭제한다.

 

git fetch [remote-name] -p

 

원격 저장소의 삭제된 브랜치를 반영하여 패치한다.

1. 이진탐색

1
2
3
4
5
6
7
8
while(start<=end){
 
    if(target==mid) break;
 
    if(target<mid) end=mid-1;
 
    else start=mid+1;
}
cs
 

2. Lower Bound : 원하는 값 이상이 처음 나오는 위치

1
2
3
4
5
6
7
8
9
while(start<end){
   
    if(target<=mid) end=mid ;
 
 
    else start=mid+1;
}
 
return end;
cs

 

3. Upper Bound : 원하는 값 초과한 값이 처음 나오는 위치 

1
2
3
4
5
6
7
8
9
while(start<end){
    
    if(target<mid) end=mid ;
 
    else start=mid+1;
}
 
return end ;
 
cs

 

'알고리즘(Algorithm) > 삼성 B형 준비' 카테고리의 다른 글

최소힙(Min_Heap) 구현  (0) 2019.12.15
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
struct Data {
    int a;
    int b;
 
    bool operator>(const Data& data) {
        return this->> data.b;
    }
};
 
struct Heap {
 
    Data data[300000];
 
    int k = 1;
 
    void init() {
        k = 1;
    }
 
    bool empty() {
        if (k == 1return true;
        return false;
    }
 
    void push(Data input) {
        int cur = k++;
        data[cur] = input;
        int par = cur / 2;
 
        while (1) {
            if (par == 0break;
            if (data[par] > data[cur]) {
 
                swap(data[par], data[cur]);
 
                cur = par;
                par = cur / 2;
            }
            else break;
        }
    }
 
    Data pop() {
 
        Data result = data[1];
        swap(data[1], data[k - 1]);
        k--;
 
        int cur = 1;
        while (1) {
            int child = cur * 2;
            if (child >= k) break;//자식이 없다면 종료
 
            if (child + 1 < k) {//오른쪽 자식이 존재한다면
                if (data[child] > data[child + 1]) child += 1;
            }
 
            if (data[cur] > data[child].) {
                swap(data[cur], data[child]);
                cur = child;
            }
            else break;
        }
 
        return result;
    }
};
cs

'알고리즘(Algorithm) > 삼성 B형 준비' 카테고리의 다른 글

이분탐색  (0) 2019.12.22

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
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.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
 
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
 
import androidx.annotation.Nullable;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
 
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
 
import java.io.File;
import java.net.URL;
import java.util.HashMap;
 
public class MainActivity extends AppCompatActivity {
 
    RecyclerView recyclerView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
 
        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        recyclerView.setLayoutManager(layoutManager);
 
        final SingerAdapter adapter = new SingerAdapter(getApplicationContext());
 
        adapter.addItem(new SingerItem("소녀시대""010-2131-5133"));
        adapter.addItem(new SingerItem("티아라""010-2221-4353"));
        adapter.addItem(new SingerItem("여자친구""010-2134-2222"));
 
        adapter.setOnItemClickListener(new SingerAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(SingerAdapter.ViewHolder holder, View view, int position) {
                SingerItem item = adapter.getItem(position);
 
                Toast.makeText(getApplicationContext(), "아이템 선택됨 : " + item.getName() + ", " + holder.textView2.getText().toString(), Toast.LENGTH_LONG).show();
            }
        });
 
        recyclerView.setAdapter(adapter);
 
 
    }
}
cs

 

SingerAdapter2(이게 더 맞는거 같음)

...더보기
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package com.example.boostcoursepractice;
 
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
 
import androidx.annotation.LongDef;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
 
import java.util.ArrayList;
 
public class SingerAdapter extends RecyclerView.Adapter<SingerAdapter.ViewHolder> {
 
    Context context;
 
    ArrayList<SingerItem> items = new ArrayList<SingerItem>();
 
    OnItemClickListener listener;
 
    public interface OnItemClickListener {
        public void onItemClick(ViewHolder holder, View view, int position);
    }
 
    public SingerAdapter(Context context) {
        this.context = context;
    }
 
    @Override
    public int getItemCount() {
        return items.size();
    }
 
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View itemView = inflater.inflate(R.layout.singer_item, parent, false);
 
        return new ViewHolder(itemView);
    }
 
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        SingerItem item = items.get(position);
        holder.setItem(item);
 
        holder.position = position;
    }
 
    public void addItem(SingerItem item) {
        items.add(item);
    }
 
    public void addItems(ArrayList<SingerItem> items) {
        this.items = items;
    }
 
    public SingerItem getItem(int position) {
        return items.get(position);
    }
 
    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }
 
    class ViewHolder extends RecyclerView.ViewHolder {
 
        TextView textView;
        TextView textView2;
        int position;
 
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.textView);
            textView2 = itemView.findViewById(R.id.textView2);
 
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (listener != null) {
                        Log.d("jjh""포지션 : " + position);
                        listener.onItemClick(ViewHolder.this, view, position);
                    }
                }
            });
        }
 
        public void setItem(SingerItem item) {
            textView.setText(item.getName());
            textView2.setText(item.getMobile());
        }
    }
}
 
cs

 

SingerAdapter

...더보기
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package com.example.boostcoursepractice;
 
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
 
import androidx.annotation.LongDef;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
 
import java.util.ArrayList;
 
public class SingerAdapter extends RecyclerView.Adapter<SingerAdapter.ViewHolder>{
 
    Context context ;
 
    ArrayList<SingerItem> items = new ArrayList<SingerItem>();
 
    OnItemClickListener listener;
 
    int num = 0 ;
 
    public static interface OnItemClickListener{
        public void onItemClick(ViewHolder holder , View view, int position);
    }
 
    public SingerAdapter(Context context){
        this.context = context ;
    }
 
    @Override
    public int getItemCount() {
        return items.size();
    }
 
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View itemView = inflater.inflate(R.layout.singer_item, parent, false);
 
        return new ViewHolder(itemView, num++);
    }
 
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        SingerItem item = items.get(position);
        holder.setItem(item);
 
        holder.setOnItemClickListener(listener);
    }
 
    public void addItem(SingerItem item){
        items.add(item);
    }
 
    public void addItems(ArrayList<SingerItem> items){
        this.items = items ;
    }
 
    public SingerItem getItem(int position){
        return items.get(position);
    }
 
    public void setOnItemClickListener(OnItemClickListener listener){
        this.listener = listener;
    }
 
    static class ViewHolder extends RecyclerView.ViewHolder{
 
        TextView textView;
        TextView textView2;
 
        OnItemClickListener listener ;
 
        public ViewHolder(@NonNull View itemView, final int position) {
            super(itemView);
            textView = itemView.findViewById(R.id.textView);
            textView2 = itemView.findViewById(R.id.textView2);
 
            itemView.setOnClickListener(new View.OnClickListener() {
 
                @Override
                public void onClick(View view) {
                    if(listener != null){
                        Log.d("jjh","포지션 : " + position);
                        listener.onItemClick(ViewHolder.this, view, position);
                    }
                }
            });
        }
 
        public void setItem(SingerItem item){
            textView.setText(item.getName());
            textView2.setText(item.getMobile());
        }
 
        public void setOnItemClickListener(OnItemClickListener listener){
            this.listener = listener;
        }
 
    }
}
 
cs

 

SingerItem

...더보기
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
package com.example.boostcoursepractice;
 
public class SingerItem {
 
    private String name ;
    private String mobile;
 
    public SingerItem(String name, String mobile) {
        this.name = name;
        this.mobile = mobile;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getMobile() {
        return mobile;
    }
 
    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
}
 
cs

 

activity_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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">
 
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />
 
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></androidx.recyclerview.widget.RecyclerView>
 
</LinearLayout>
cs

 

singer_item.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="이름"
        android:textColor="@color/colorAccent"
        android:textSize="30dp" />
 
    <TextView
        android:id="@+id/textView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="전화번호"
        android:textColor="@color/design_default_color_primary"
        android:textSize="20dp" />
</LinearLayout>
cs

 

우선 리싸이클러뷰는 리스트뷰를 만드는 것과 비슷하다. 하지만 여기에 뷰홀더라는 개념이 추가가 된다. 뷰홀더는 그냥 아이템 하나를 가지고 있는 클래스라고 생각하면 된다. 그리고 그 아이템을 가지고 있는 뷰홀더가 모여 어댑터가 되고 그 어댑터를 리싸이클뷰에 추가하면 완료된다. 우선 아이템의 레이아웃인 singer_item.xml 만들고 아이템의 데이터인 SingerItem 자바 클래스를 만들어 준다.(리스트뷰와 동일) 그 다음은 리싸이클뷰 어댑터를 만들어 준다 여기서는 SingerAdapter라고 만들어 주었다. 어댑터의 코드를 보면 

 

 @NonNull

    @Override

    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View itemView = inflater.inflate(R.layout.singer_item, parent, false);

 

        return new ViewHolder(itemView, num++);

    }

 

    @Override

    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        SingerItem item = items.get(position);

        holder.setItem(item);

 

        holder.setOnItemClickListener(listener);

    }

 

이런 코드가 있는데 onCreateViewHolder라는 콜백함수는 뷰홀더가 만들어 질 때 호출되는데 여기서 아까 만들어준 singer_item.xml을 인플레이션해주고 홀더 인스턴스 안에 넣어 리턴해준다. onBindViewHolder는 뷰와 홀더가 바인드 될 때 실행되는 함수로 여기에서 setItem으로 뷰 안에 여러 뷰들을 설정해준다. 이렇게 하고 다시 MainActivity로 돌아와 리사이클러뷰에 어댑터를 설정해 주면 되는데 그전에 

 

recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

 

        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);

        recyclerView.setLayoutManager(layoutManager);

 

위 처럼 레이아웃매너저를 만들어 리싸이클러뷰에 설정해 주어야 한다.

 

마지막으로 아이템이 클릭 되었을 때의 리스너는 따로 구현되어 있지 않기 때문에 직접 만들어주어야 한다. 여기에서는 어댑터 클래스에 구현해 주었다. 

 

 

 

결과화면

 

+ Recent posts