kill -9 pid 를 사용할 경우 프로세스가 강제종료 됩니다.
현재 어떤 작업을 진행중이라면 문제가 될 수 있습니다.
가급적이면 kill -15 옵션을 사용하는 것을 권장합니다.
만약 스프링 어플리케이션이라면
application.properties에 server.shutdown=graceful 옵션을 적용하면 안전하게 종료됩니다.
(스프링부트 2.3.0 버전부터 가능한것으로 확인 됐습니다.)
자바 프로세스의 경우
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
}
});
위 함수를 통해서 안전하게 프로세스를 종료시킬 수 있습니다.
2020년 6월 22일 월요일
2020년 5월 10일 일요일
Spring Boot AJP 설정
Apache의 mod_jk 구성이 필요합니다.
- Tomcat
@Configuration
public class TomcatConfiguration {
@Bean
public WebServerFactory servletContainer() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
Connector ajp = new Connector("AJP/1.3");
ajp.setPort(8009);
ajp.setSecure(false);
ajp.setAllowTrace(false);
ajp.setScheme("http");
ProtocolHandler protocolHandler = ajp.getProtocolHandler();
if (protocolHandler instanceof AbstractAjpProtocol) {
AbstractAjpProtocol<?> abstractAjpProtocol = (AbstractAjpProtocol<?>) protocolHandler;
abstractAjpProtocol.setSecretRequired(false);
}
factory.addAdditionalTomcatConnectors(ajp);
return factory;
}
}
메이븐 설정은 spring-boot-starter-tomcat이 필요합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
- Undertow
@Configuration
public class UndertowConfiguration {
@Bean
public ServletWebServerFactory servletContainer() {
UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
@Override
public void customize(Builder builder) {
builder.addAjpListener(8009, "127.0.0.1");
}
});
return factory;
}
}
메이븐 설정은 spring-boot-starter-undertow이 필요하고 undertow 구성 시 spring-boot-starter-tomcat을 제외해야 합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
- Tomcat
@Configuration
public class TomcatConfiguration {
@Bean
public WebServerFactory servletContainer() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
Connector ajp = new Connector("AJP/1.3");
ajp.setPort(8009);
ajp.setSecure(false);
ajp.setAllowTrace(false);
ajp.setScheme("http");
ProtocolHandler protocolHandler = ajp.getProtocolHandler();
if (protocolHandler instanceof AbstractAjpProtocol) {
AbstractAjpProtocol<?> abstractAjpProtocol = (AbstractAjpProtocol<?>) protocolHandler;
abstractAjpProtocol.setSecretRequired(false);
}
factory.addAdditionalTomcatConnectors(ajp);
return factory;
}
}
메이븐 설정은 spring-boot-starter-tomcat이 필요합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
- Undertow
@Configuration
public class UndertowConfiguration {
@Bean
public ServletWebServerFactory servletContainer() {
UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
@Override
public void customize(Builder builder) {
builder.addAjpListener(8009, "127.0.0.1");
}
});
return factory;
}
}
메이븐 설정은 spring-boot-starter-undertow이 필요하고 undertow 구성 시 spring-boot-starter-tomcat을 제외해야 합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
라벨:
AJP,
Spring Boot,
tomcat,
Undertow
위치:
대한민국
2020년 3월 13일 금요일
ModSecurity MIME-TYPE 추가하기
Apache의 ModSecurity가 설정된 경우
임의의 MIME-TYPE를 설정할 때 403 에러 응답을 하는 경우를 볼 수 있습니다.
이 경우 ModSecurity 설정 파일에 다음과 같이 내용을 추가합니다.
SecAction \
"id:900990,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:'tx.allowed_request_content_type=application/xxx|application/xxxx', \
setvar:tx.crs_setup_version=320"
구분자는 | 문자입니다.
타입을 추가한 뒤 아파치를 재시작하고 200 OK로 처리 됩니다.
임의의 MIME-TYPE를 설정할 때 403 에러 응답을 하는 경우를 볼 수 있습니다.
이 경우 ModSecurity 설정 파일에 다음과 같이 내용을 추가합니다.
SecAction \
"id:900990,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:'tx.allowed_request_content_type=application/xxx|application/xxxx', \
setvar:tx.crs_setup_version=320"
구분자는 | 문자입니다.
타입을 추가한 뒤 아파치를 재시작하고 200 OK로 처리 됩니다.
라벨:
아파치,
mime,
ModSecurity
위치:
대한민국
2020년 3월 12일 목요일
아파치 mod_security2 설치 - 윈도우 환경
0. 적용환경
운영체제 : Windows 10 64bit
Apache 버전 : Apache2.4
mod_security 버전 : mod_security-2.9.3-win64-VS16
1. mod_security 설치
mod_security-2.9.3-win64-VS16.zip 파일 다운로드
다운로드 : https://www.apachelounge.com/download/
- yajl.dll 설치
apache24/bin 디렉토리에 yajl.dll 복사
- mod_security2.so 설치
apache24/modules 디렉토리에 mod_security2.so 복사
2. owasp-modsecurity-crs 설치
owasp-modsecurity-crs 다운로드
owasp-modsecurity-crs-3.2.0 버전으로 설치했습니다.
다운로드 : https://github.com/SpiderLabs/owasp-modsecurity-crs
- owasp-modsecurity-crs 설정
apache24/conf 디렉토리에 owasp-modsecurity-crs 디렉토리를 만들고
압축파일 내에 있는 crs-setup.conf.example파일과 rules 디렉토리를 복사합니다.
그리고 crs-setup.conf.example 파일 이름을 crs-setup.conf로 변경합니다.
3. crs-setup.conf 설정
crs-setup.conf 파일을 열어 최상단에 다음과 같이 수정합니다.
SecRuleEngine On
SecDefaultAction "deny,phase:2,status:403"
ServerTokens Full
ServerSignature Off
SecServerSignature "TestServer"
4. httpd.conf 설정
LoadModule unique_id_module modules/mod_unique_id.so
LoadModule security2_module modules/mod_security2.so
<IfModule security2_module>
Include conf/owasp-modsecurity-crs/crs-setup.conf
Include conf/owasp-modsecurity-crs/rules/*.conf
</IfModule>
5. 요청 응답 해더 확인
아파치를 재시작하고
응답 헤더에 Server가 TestServer 값으로 수정된 것을 확인합니다.
http://localhost
운영체제 : Windows 10 64bit
Apache 버전 : Apache2.4
mod_security 버전 : mod_security-2.9.3-win64-VS16
1. mod_security 설치
mod_security-2.9.3-win64-VS16.zip 파일 다운로드
다운로드 : https://www.apachelounge.com/download/
- yajl.dll 설치
apache24/bin 디렉토리에 yajl.dll 복사
- mod_security2.so 설치
apache24/modules 디렉토리에 mod_security2.so 복사
2. owasp-modsecurity-crs 설치
owasp-modsecurity-crs 다운로드
owasp-modsecurity-crs-3.2.0 버전으로 설치했습니다.
다운로드 : https://github.com/SpiderLabs/owasp-modsecurity-crs
- owasp-modsecurity-crs 설정
apache24/conf 디렉토리에 owasp-modsecurity-crs 디렉토리를 만들고
압축파일 내에 있는 crs-setup.conf.example파일과 rules 디렉토리를 복사합니다.
그리고 crs-setup.conf.example 파일 이름을 crs-setup.conf로 변경합니다.
3. crs-setup.conf 설정
crs-setup.conf 파일을 열어 최상단에 다음과 같이 수정합니다.
SecRuleEngine On
SecDefaultAction "deny,phase:2,status:403"
ServerTokens Full
ServerSignature Off
SecServerSignature "TestServer"
4. httpd.conf 설정
LoadModule unique_id_module modules/mod_unique_id.so
LoadModule security2_module modules/mod_security2.so
<IfModule security2_module>
Include conf/owasp-modsecurity-crs/crs-setup.conf
Include conf/owasp-modsecurity-crs/rules/*.conf
</IfModule>
5. 요청 응답 해더 확인
아파치를 재시작하고
응답 헤더에 Server가 TestServer 값으로 수정된 것을 확인합니다.
http://localhost
라벨:
아파치,
아파치헤더,
apache,
header server,
mod_security2,
windows
위치:
대한민국
2020년 3월 10일 화요일
우분투 - 아파치 톰캣 연동
apache2, tomcat9 연동예제입니다.
1. 설치
# apt-get install -y apache2
# service apache2 start
아파치2 접속확인
http://localhost
2. 톰캣설치
# apt-get install -y openjdk-8-jdk
자바가 필수로 설치된 환경에서 설치합니다.
/usr/share/tomcat9경로에 설치합니다.
# cd /usr/share
# wget http://apache.mirror.cdnetworks.com/tomcat/tomcat-9/v9.0.31/bin/apache-tomcat-9.0.31.tar.gz
# tar -zxvf apache-tomcat-9.0.31.tar.gz
# mv apache-tomcat-9.0.31 tomcat9
# rm apache-tomcat-9.0.31.tar.gz
톰캣 접속확인
http://localhost:8080
3. mod-jk 설치
# apt-get install libapache2-mod-jk
4. /etc/libapache2-mod-jk/workers.properties 수정
# which java
/usr/bin/java
# readlink /usr/bin/java
/etc/alternatives/java
# readlink /etc/alternatives/java
/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
readlink /etc/alternatives/java에서 확인된 경로와 톰캣 설치 경로를 workers.properties 파일에 설정합니다.
# vi /etc/libapache2-mod-jk/workers.properties
workers.tomcat_home=/usr/share/tomcat9
workers.java_home=/usr/lib/jvm/java-8-openjdk-amd64
5. 톰캣 server.xml 파일 수정
# vi /usr/share/tomcat9/conf/server.xml
<Connector protocol="AJP/1.3"
port="8009"
address="0.0.0.0"
secretRequired="false"
redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost" jvmRoute="ajp13_worker">
Connector의 secretRequired, address 두 설정에 오류가 있으면 연동이 안될 수 있습니다.
worker 기본 설정값인 ajp13_worker를 jvmRoute에 입력합니다.
톰캣9 재시작
# sh /usr/share/tomcat9/bin/shutdown.sh
# sh /usr/share/tomcat9/bin/startup.sh
6. /etc/apache2/sites-enabled/000-default.conf 수정
# vi /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
DocumentRoot /usr/share/tomcat9/webapps/ROOT
7. /etc/apache2/apache2.conf 수정
# vi /etc/apache2/apache2.conf
ServerName localhost
서버네임이 생략된경우 추가합니다.
8. 아파치2 재시작
# service apache2 restart
9. 접속확인
http://localhost
만약 접속이 안된다면 톰캣과 아차피 모두 재시작하고 확인합니다.
에러가 발생한다면 /var/log/apache2/ 경로에서 아파치 로그를 확인합니다.
1. 설치
# apt-get install -y apache2
# service apache2 start
아파치2 접속확인
http://localhost
2. 톰캣설치
# apt-get install -y openjdk-8-jdk
자바가 필수로 설치된 환경에서 설치합니다.
/usr/share/tomcat9경로에 설치합니다.
# cd /usr/share
# wget http://apache.mirror.cdnetworks.com/tomcat/tomcat-9/v9.0.31/bin/apache-tomcat-9.0.31.tar.gz
# tar -zxvf apache-tomcat-9.0.31.tar.gz
# mv apache-tomcat-9.0.31 tomcat9
# rm apache-tomcat-9.0.31.tar.gz
# sh /usr/share/tomcat9/bin/startup.sh
톰캣 접속확인
http://localhost:8080
3. mod-jk 설치
# apt-get install libapache2-mod-jk
4. /etc/libapache2-mod-jk/workers.properties 수정
# which java
/usr/bin/java
# readlink /usr/bin/java
/etc/alternatives/java
# readlink /etc/alternatives/java
/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
readlink /etc/alternatives/java에서 확인된 경로와 톰캣 설치 경로를 workers.properties 파일에 설정합니다.
# vi /etc/libapache2-mod-jk/workers.properties
workers.tomcat_home=/usr/share/tomcat9
workers.java_home=/usr/lib/jvm/java-8-openjdk-amd64
5. 톰캣 server.xml 파일 수정
# vi /usr/share/tomcat9/conf/server.xml
<Connector protocol="AJP/1.3"
port="8009"
address="0.0.0.0"
secretRequired="false"
redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost" jvmRoute="ajp13_worker">
Connector의 secretRequired, address 두 설정에 오류가 있으면 연동이 안될 수 있습니다.
worker 기본 설정값인 ajp13_worker를 jvmRoute에 입력합니다.
톰캣9 재시작
# sh /usr/share/tomcat9/bin/shutdown.sh
# sh /usr/share/tomcat9/bin/startup.sh
6. /etc/apache2/sites-enabled/000-default.conf 수정
# vi /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
ServerName localhost
JkMount /* ajp13_workerDocumentRoot /usr/share/tomcat9/webapps/ROOT
</VirtualHost>
# vi /etc/apache2/apache2.conf
ServerName localhost
서버네임이 생략된경우 추가합니다.
8. 아파치2 재시작
# service apache2 restart
9. 접속확인
http://localhost
만약 접속이 안된다면 톰캣과 아차피 모두 재시작하고 확인합니다.
에러가 발생한다면 /var/log/apache2/ 경로에서 아파치 로그를 확인합니다.
2019년 6월 7일 금요일
안드로이드 RecyclerView 예제
- RecyclerView.ViewHolder 적용
- androidx.recyclerview.widget.DiffUtil 적용
1. RecyclerView.Adapter 구현
public class TextRecyclerAdapter extends RecyclerView.Adapter<TextRecyclerAdapter.Holder> {
private LayoutInflater inflater;
private final ArrayList<String> items = new ArrayList<>();
public void updateList(final List<String> newItems) {
TextDiff callback = new TextDiff(this.items, newItems);
DiffUtil.DiffResult result = DiffUtil.calculateDiff(callback);
this.items.clear();
this.items.addAll(newItems);
result.dispatchUpdatesTo(this);
}
@NonNull
@Override
public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (inflater == null)
inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
return new Holder(itemView);
}
@Override
public void onBindViewHolder(@NonNull Holder holder, int position) {
holder.bindData(getItem(position));
}
public String getItem(int position) {
return items != null && position < getItemCount() ? items.get(position) : null;
}
@Override
public int getItemCount() {
return items == null ? 0 : items.size();
}
static class Holder extends RecyclerView.ViewHolder {
private final TextView text;
public Holder(@NonNull View itemView) {
super(itemView);
this.text = itemView.findViewById(android.R.id.text1);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Object tag = v.getTag();
if (tag instanceof String) {
}
}
});
}
public void bindData(String item) {
itemView.setTag(item);
if (item == null)
return;
text.setText(item);
}
}
static class TextDiff extends DiffUtil.Callback {
private final List<String> oldItems;
private final List<String> newItems;
public TextDiff(List<String> oldItems, List<String> newItems) {
this.oldItems = oldItems;
this.newItems = newItems;
}
@Override
public int getOldListSize() {
return oldItems.size();
}
@Override
public int getNewListSize() {
return newItems.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
if (oldItemPosition > newItemPosition)
return false;
return oldItems.get(oldItemPosition).equals(newItems.get(oldItemPosition));
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
if (oldItemPosition > newItemPosition)
return false;
return oldItems.get(oldItemPosition).equals(newItems.get(oldItemPosition));
}
}
}
- ViewHolder 클래스를 구현해서 사용한다.
- DiffUtil 클래스를 구현해서 리스트 갱신을 효율적으로 구현한다.
2. RecyclerView 구현
public class RecyclerListFragment extends Fragment {
public RecyclerListFragment() {
// Required empty public constructor
}
public static RecyclerListFragment newInstance() {
RecyclerListFragment fragment = new RecyclerListFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recycler_list, container, false);
RecyclerView recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(recyclerView.getContext());
linearLayoutManager.setOrientation(RecyclerView.VERTICAL);
TextRecyclerAdapter textRecyclerAdapter = new TextRecyclerAdapter();
recyclerView.setAdapter(textRecyclerAdapter);
ArrayList<String> items = new ArrayList<>();
items.add("Text Item 1");
items.add("Text Item 2");
items.add("Text Item 3");
textRecyclerAdapter.updateList(items);
return view;
}
}
- updateList를 호출하면 DiffUtil 기능으로 리스트가 자연스럽게 갱신된다.
- androidx.recyclerview.widget.DiffUtil 적용
1. RecyclerView.Adapter 구현
public class TextRecyclerAdapter extends RecyclerView.Adapter<TextRecyclerAdapter.Holder> {
private LayoutInflater inflater;
private final ArrayList<String> items = new ArrayList<>();
public void updateList(final List<String> newItems) {
TextDiff callback = new TextDiff(this.items, newItems);
DiffUtil.DiffResult result = DiffUtil.calculateDiff(callback);
this.items.clear();
this.items.addAll(newItems);
result.dispatchUpdatesTo(this);
}
@NonNull
@Override
public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (inflater == null)
inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
return new Holder(itemView);
}
@Override
public void onBindViewHolder(@NonNull Holder holder, int position) {
holder.bindData(getItem(position));
}
public String getItem(int position) {
return items != null && position < getItemCount() ? items.get(position) : null;
}
@Override
public int getItemCount() {
return items == null ? 0 : items.size();
}
static class Holder extends RecyclerView.ViewHolder {
private final TextView text;
public Holder(@NonNull View itemView) {
super(itemView);
this.text = itemView.findViewById(android.R.id.text1);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Object tag = v.getTag();
if (tag instanceof String) {
}
}
});
}
public void bindData(String item) {
itemView.setTag(item);
if (item == null)
return;
text.setText(item);
}
}
static class TextDiff extends DiffUtil.Callback {
private final List<String> oldItems;
private final List<String> newItems;
public TextDiff(List<String> oldItems, List<String> newItems) {
this.oldItems = oldItems;
this.newItems = newItems;
}
@Override
public int getOldListSize() {
return oldItems.size();
}
@Override
public int getNewListSize() {
return newItems.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
if (oldItemPosition > newItemPosition)
return false;
return oldItems.get(oldItemPosition).equals(newItems.get(oldItemPosition));
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
if (oldItemPosition > newItemPosition)
return false;
return oldItems.get(oldItemPosition).equals(newItems.get(oldItemPosition));
}
}
}
- ViewHolder 클래스를 구현해서 사용한다.
- DiffUtil 클래스를 구현해서 리스트 갱신을 효율적으로 구현한다.
2. RecyclerView 구현
public class RecyclerListFragment extends Fragment {
public RecyclerListFragment() {
// Required empty public constructor
}
public static RecyclerListFragment newInstance() {
RecyclerListFragment fragment = new RecyclerListFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recycler_list, container, false);
RecyclerView recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(recyclerView.getContext());
linearLayoutManager.setOrientation(RecyclerView.VERTICAL);
TextRecyclerAdapter textRecyclerAdapter = new TextRecyclerAdapter();
recyclerView.setAdapter(textRecyclerAdapter);
ArrayList<String> items = new ArrayList<>();
items.add("Text Item 1");
items.add("Text Item 2");
items.add("Text Item 3");
textRecyclerAdapter.updateList(items);
return view;
}
}
- updateList를 호출하면 DiffUtil 기능으로 리스트가 자연스럽게 갱신된다.
라벨:
안드로이드,
DiffUtil,
RecyclerView,
ViewHolder
위치:
대한민국
안드로이드 BaseAdapter 예제
- android.widget.BaseAdapter 적용
- ViewHolder 방식 사용
1. BaseAdapter 구현
public class TextListAdapter extends BaseAdapter {
private LayoutInflater inflater;
static class Holder {
private final TextView text;
public Holder(View itemView) {
this.text = itemView.findViewById(android.R.id.text1);
}
void bindData(String item) {
text.setText(item);
}
}
private final ArrayList<String> contentItems = new ArrayList<>();
@Override
public int getCount() {
return contentItems == null ? 0 : contentItems.size();
}
@Override
public String getItem(int position) {
return contentItems != null && position < getCount() ? contentItems.get(position) : null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = LayoutInflater.from(parent.getContext());
Holder holder;
if (convertView == null) {
convertView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
holder = new Holder(convertView);
} else {
holder = (Holder) convertView.getTag();
}
holder.bindData(getItem(position));
return convertView;
}
}
- Holder 클래스(ViewHolder)를 View 태그에 넣어서 재활용한다.
- ListView 어뎁터 구현의 가장 기본이 되는 방식.
2. ListView 구현
public class TextListFragment extends Fragment {
public TextListFragment() {
// Required empty public constructor
}
public static TextListFragment newInstance() {
TextListFragment fragment = new TextListFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ArrayList<String> items = new ArrayList<>();
items.add("Text Item 1");
items.add("Text Item 2");
items.add("Text Item 3");
View view = inflater.inflate(R.layout.fragment_text_list, container, false);
ListView listView = view.findViewById(R.id.listView);
listView.setAdapter(new TextListAdapter(items));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Object item = parent.getItemAtPosition(position);
if (item instanceof String) {
}
}
});
return view;
}
}
- AdapterView에서 아이템을 가져와 클릭이벤트에 해당하는 아이템을 불러온다.
- ViewHolder 방식 사용
1. BaseAdapter 구현
public class TextListAdapter extends BaseAdapter {
private LayoutInflater inflater;
static class Holder {
private final TextView text;
public Holder(View itemView) {
this.text = itemView.findViewById(android.R.id.text1);
}
void bindData(String item) {
text.setText(item);
}
}
private final ArrayList<String> contentItems = new ArrayList<>();
@Override
public int getCount() {
return contentItems == null ? 0 : contentItems.size();
}
@Override
public String getItem(int position) {
return contentItems != null && position < getCount() ? contentItems.get(position) : null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = LayoutInflater.from(parent.getContext());
Holder holder;
if (convertView == null) {
convertView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
holder = new Holder(convertView);
} else {
holder = (Holder) convertView.getTag();
}
holder.bindData(getItem(position));
return convertView;
}
}
- Holder 클래스(ViewHolder)를 View 태그에 넣어서 재활용한다.
- ListView 어뎁터 구현의 가장 기본이 되는 방식.
2. ListView 구현
public class TextListFragment extends Fragment {
public TextListFragment() {
// Required empty public constructor
}
public static TextListFragment newInstance() {
TextListFragment fragment = new TextListFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ArrayList<String> items = new ArrayList<>();
items.add("Text Item 1");
items.add("Text Item 2");
items.add("Text Item 3");
View view = inflater.inflate(R.layout.fragment_text_list, container, false);
ListView listView = view.findViewById(R.id.listView);
listView.setAdapter(new TextListAdapter(items));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Object item = parent.getItemAtPosition(position);
if (item instanceof String) {
}
}
});
return view;
}
}
- AdapterView에서 아이템을 가져와 클릭이벤트에 해당하는 아이템을 불러온다.
라벨:
안드로이드,
BaseAdapter
위치:
대한민국
피드 구독하기:
글 (Atom)