2019년 2월 27일 수요일
안드로이드 RecyclerView 예제
- androidx 기준
- 클릭 이벤트, Diffutil 구현 샘플
1. app module dependencies 설정
2019.02.27 기준
implementation 'androidx.recyclerview:recyclerview-selection:1.0.0'
레퍼런스 : https://developer.android.com/jetpack/androidx/migrate
2. DiffUtil.Callback 작성
- DiffUtilCallback
public class DiffUtilCallback extends DiffUtil.Callback {
private final List<TextItem> oldList;
private final List<TextItem> newList;
public DiffUtilCallback(List<TextItem> oldList, List<TextItem> newList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList == null ? 0 : oldList.size();
}
@Override
public int getNewListSize() {
return newList == null ? 0 : newList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).getId() == newList.get(newItemPosition).getId();
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).getText().equals(newList.get(newItemPosition).getText());
}
}
3. RecyclerView.Adapter 구현
- TextItemAdapter
public abstract class TextItemAdapter extends RecyclerView.Adapter<Holder> implements View.OnClickListener {
private final List<TextItem> list = new ArrayList<>();
@Override
public void onClick(View v) {
ViewParent parent = v.getParent();
if (parent instanceof RecyclerView) {
RecyclerView rv = (RecyclerView) parent;
// 클릭된 포지션 찾기
int position = rv.getChildAdapterPosition(v);
TextItem item = list.get(position);
onItemClick(rv, v, position, item);
}
}
/**
* 클릭 이벤트
*
* @param rv
* @param view
* @param position
* @param item
*/
public abstract void onItemClick(RecyclerView rv, View view, int position, TextItem item);
@NonNull
@Override
public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
// 클릭 이벤트
view.setOnClickListener(this);
return new Holder(view);
}
@Override
public void onBindViewHolder(@NonNull Holder holder, int position) {
holder.bindItem(list.get(position));
}
@Override
public int getItemCount() {
return list.size();
}
public void updateList(List<TextItem> newList) {
// 리스트 갱신
DiffUtilCallback diffUtilCallback = new DiffUtilCallback(list, newList);
DiffUtil.DiffResult result = DiffUtil.calculateDiff(diffUtilCallback);
this.list.clear();
this.list.addAll(newList);
result.dispatchUpdatesTo(this);
}
}
4. 샘플코드
소스코드
APK
안드로이드 UI 네비게이션
- 네비게이션 레퍼런스
https://developer.android.com/topic/libraries/architecture/navigation.html?hl=ko
- Google Codelab
https://codelabs.developers.google.com/codelabs/android-navigation/#0
1. res/navigation/navi.xml 작성
<navigation 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">
</navigation>
- 2019.02.27 기준 app module dependencies 설정
implementation 'android.arch.navigation:navigation-fragment:1.0.0-beta02'
*** xml 문서 정의 후 해당 문서를 오픈하면 자동으로 dependencies 설정 팝업이 표시됩니다.
2. activity_main.xml 작성
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">
<fragment
android:id="@+id/host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/navi" />
</FrameLayout>
3. MainActivity 작성
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onSupportNavigateUp() {
return Navigation.findNavController(this, R.id.host_fragment).navigateUp();
}
}
4. Fragment 생성 후 navi.xml 수정
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@id/listFragment">
<fragment
android:id="@+id/listFragment"
android:name="app.example.navigationui.ListFragment"
android:label="fragment_list"
tools:layout="@layout/fragment_list" >
<action
android:id="@+id/action_listFragment_to_textFragment"
app:destination="@id/textFragment"
app:popUpTo="@+id/listFragment" />
</fragment>
<fragment
android:id="@+id/textFragment"
android:name="app.example.navigationui.TextFragment"
android:label="fragment_text"
tools:layout="@layout/fragment_text" >
<argument
android:name="text"
app:argType="string"
android:defaultValue="-" />
</fragment>
</navigation>
5. 샘플코드
소스코드
APK
위치:
대한민국
안드로이드 커스텀 스키마
- 커스텀 URL 스키마 주소를 통해 Activity를 실행
주소 : custom://page?text=hello
1. CustomSchemeActivity 생성
public class CustomSchemeActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom);
// uri 읽기
Uri uri = getIntent().getData();
if (uri != null) {
// 파라미터 읽기
String text = uri.getQueryParameter("text");
if (TextUtils.isEmpty(text) == false) {
// 파라미터 값 표시
TextView textView = findViewById(R.id.text);
textView.setText(String.format("text = %s", text));
}
}
}
}
2. AndroidManifests 설정
<activity android:name=".CustomSchemeActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="page"
android:scheme="custom" />
</intent-filter>
</activity>
3. 동작 확인
- Intent 동작
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("custom://page?text=hello")));
- URL 동작
주소 : custom://page?text=hello
4. 샘플코드
소스코드
APK
위치:
대한민국
2019년 2월 26일 화요일
MTU 변경하기
- 윈도우10 기준입니다.
- 윈도우7의 경우 1, 2, 4번을 설정합니다.
1. CMD 창을 관리자 모드로 실행
2. 이더넷 인터페이스 정보 확인
netsh interface ipv4 show interfaces
3. global minmtu 값 설정
netsh interface ipv4 set global minmtu=500 store=active
색표시가 된 부분을 수정하시면 됩니다.
store 속성을 active로 할 경우 시스템 재부팅 후 설정이 풀립니다.
persistent값으로 설정하면 재부팅 후 설정이 유지 됩니다.
4. 인터페이스 MTU 변경
netsh interface ipv4 set subinterface "15" mtu=500 store=active
색표시가 된 부분을 수정하시면 됩니다.
store 속성을 active로 할 경우 시스템 재부팅 후 설정이 풀립니다.
persistent값으로 설정하면 재부팅 후 설정이 유지 됩니다.
2018년 11월 30일 금요일
안드로이드 화면캡체 제한하기
- 코드
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
윈도우 플래그 값을 FLAG_SECURE로 설정하면 화면을 캡쳐하거나 녹화할 수 없습니다.
adb 명령어를 통한 화면캡쳐와 화면녹화도 함께 적용 받습니다.
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
윈도우 플래그 값을 FLAG_SECURE로 설정하면 화면을 캡쳐하거나 녹화할 수 없습니다.
adb 명령어를 통한 화면캡쳐와 화면녹화도 함께 적용 받습니다.
2016년 11월 19일 토요일
톰캣 튜닝 팁
- Listener 설정
<Listener className="org.apache.catalina.security.SecurityListener" checkedOsUsers="root" />
root 계정 실행을 방지하는 기능입니다.
- Connector 튜닝
acceptCount="10"
enableLookups="false"
compression="false"
maxConnection="8192"
maxThread="100"
minSpareThreads="25"
disableUploadTimeout="true"
URIEncoding="UTF-8"
sendReasonPhrase="true"
Connector 속성을 추가하면 톰캣 성능이 개선됩니다.
항목별 세부사항은 별도 검색해서 확인해보시길 바랍니다.
* sendReasonPharse 옵션은 톰캣9 버전부터는 지원되지 않습니다.
- 인스턴스 명칭 부여
<Engine name="Catalina" defaultHost="localhost" jvmRoute="instance1">
jvmRoute를 설정하면 workers.properties를 통해 로드밸런싱을 구성할 수 있습니다.
- 세션 클러스터링
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
<Listener className="org.apache.catalina.security.SecurityListener" checkedOsUsers="root" />
root 계정 실행을 방지하는 기능입니다.
- Connector 튜닝
acceptCount="10"
enableLookups="false"
compression="false"
maxConnection="8192"
maxThread="100"
minSpareThreads="25"
disableUploadTimeout="true"
URIEncoding="UTF-8"
sendReasonPhrase="true"
Connector 속성을 추가하면 톰캣 성능이 개선됩니다.
항목별 세부사항은 별도 검색해서 확인해보시길 바랍니다.
* sendReasonPharse 옵션은 톰캣9 버전부터는 지원되지 않습니다.
- 인스턴스 명칭 부여
<Engine name="Catalina" defaultHost="localhost" jvmRoute="instance1">
jvmRoute를 설정하면 workers.properties를 통해 로드밸런싱을 구성할 수 있습니다.
- 세션 클러스터링
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
세션 클러스터링 기본코드 입니다.
자료 출처 : 출처 : https://tomcat.apache.org/tomcat-8.0-doc/cluster-howto.html#Cluster_Architecture
라벨:
세션 클러스터링,
톰캣,
Connector 튜닝,
jvmRoute,
root 계정 실행 방지,
tomcat
위치:
대한민국
라즈베리파이 - 아파치 톰캣 연동
1. libapache2-mod-jk 설치
- 사전 준비사항
아파치, 톰캣 모두 설치가 된 상태에서 진행해야 합니다.
- 설치
root@raspberrypi:~# apt-get install libapache2-mod-jk
- 000-default.conf 설정
/etc/apache2/sites-enabled/000-default.conf 파일 <VirtualHost *:80> 다음 행에 다음 내용을 추가합니다.
root@raspberrypi:~# vi /etc/apache2/sites-enabled/000-default.conf
- workers.properties 파일 생성
root@raspberrypi:~# vi /etc/apache2/workers.properties
- 사전 준비사항
아파치, 톰캣 모두 설치가 된 상태에서 진행해야 합니다.
- 설치
root@raspberrypi:~# apt-get install libapache2-mod-jk
2. 아파치 설정
- apache2.conf 수정
/usr/lib/apache2/modules/mod_jk.so 파일이 있는지 확인 한 후
/etc/apache2/apache2.conf 파일 맨 아래 다음과 같이 수정합니다.
root@raspberrypi:~# vi /etc/apache2/apache2.conf
추가 내용
#JK_MODULE
LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so
/etc/apache2/sites-enabled/000-default.conf 파일 <VirtualHost *:80> 다음 행에 다음 내용을 추가합니다.
root@raspberrypi:~# vi /etc/apache2/sites-enabled/000-default.conf
추가내용
JkMount /* loadbalancer- workers.properties 파일 생성
root@raspberrypi:~# vi /etc/apache2/workers.properties
추가내용
vi /etc/apache2/workers.properties
workers.java_home=/usr/lib/jvm/java-8-openjdk-armhf
worker.list=loadbalancer
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=instance1
worker.loadbalancer.sticky_session=1
worker.instance1.type=ajp13
worker.instance1.host=localhost
worker.instance1.port=8009
worker.instance1.lbfactor=1
- 톰캣 설정 확인
worker.loadbalancer.balanced_workers=instance1 라인 내용 중 instance1이 톰캣과 동일해야 합니다.
톰캣 설정 파일 server.xml을 수정합니다.
root@raspberrypi:~# vi /opt/tomcat/instance1/conf/server.xml
문서 중간 쯤
<Engine name="Catalina" defaultHost="localhost">
라인에 jvmRoute가 있는지 확인하고 수정합니다.
확인 및 수정
<Engine name="Catalina" defaultHost="localhost" jvmRoute="instance1">
- httpd-jk.conf 설정
root@raspberrypi:~# vi /etc/libapache2-mod-jk/httpd-jk.conf
JkWorkersFile /etc/libapache2-mod-jk/workers.properties 내용을 다음과 같이 수정합니다.
#JkWorkersFile /etc/libapache2-mod-jk/workers.properties
JkWorkersFile /etc/apache2/workers.properties
3. 서비스 재시작
- 톰캣 실행
root@raspberrypi:~# sh /opt/tomcat/instance1/bin/startup.sh
톰캣이 이미 실행중이라면
root@raspberrypi:~# sh /opt/tomcat/instance1/bin/shutdown.sh
root@raspberrypi:~# sh /opt/tomcat/instance1/bin/startup.sh
- 아파치 재실행
root@raspberrypi:~# service apache2 restart
- 접속 확인
80포트로 접속을 했을 때 톰캣으로 이동합니다.
피드 구독하기:
글 (Atom)