안녕하세요.
제 블로그에 오신 분들, 행복소통 청원 지지 좀 부탁드리겠습니다.
청원하기 URL
https://www.seongnam.go.kr/cheongwon/cheongwonView.do?menuIdx=1001464&idx=1129
성남 용인지역의 오리·동천역 SRT 역사 추가 설치 사업의 타당성 조사 진행 요청
휴대폰 청원 지지 방법 안내
안녕하세요.
제 블로그에 오신 분들, 행복소통 청원 지지 좀 부탁드리겠습니다.
청원하기 URL
https://www.seongnam.go.kr/cheongwon/cheongwonView.do?menuIdx=1001464&idx=1129
성남 용인지역의 오리·동천역 SRT 역사 추가 설치 사업의 타당성 조사 진행 요청
휴대폰 청원 지지 방법 안내
y = f(x) 형태의 함수로 구성된 프로그래밍 기법
Java 8에서 함수형 프로그래밍 방식인 람다식을 지원한다.
객체지향 프로그래밍보다는 함수형 프로그래밍에 가깝다고 할 수 있다.
람다식이란? 함수(메서드)를 간단한 ‘식(Expression)’으로 표현하는 방법
- 함수는 클래스에 독립적, 메소드는 클래스에 종속적
- 메서드의 이름과 반환타입을 제거하고 ‘->’를 블록{} 앞에 추가한다.
- 반환값이 있는 경우, 식이나 값만 적고 return문 생략 가능(끝에‘;’안 붙임)
- 매개변수의 타입이 추론 가능하면 생략가능(대부분의 경우 생략가능)
- 매개변수가 하나인 경우, 괄호() 생략가능(타입이 없을 때만)
- 블록 안의 문장이 하나뿐 일 때, 괄호{}생략가능(끝에 ‘;’ 안 붙임)
- 단, 하나뿐인 문장이 return문이면 괄호{} 생략불가
람다식 장점
1. 코드를 간결하게 만들 수 있다.
2. 코드가 간결하고 식에 개발자의 의도가 명확히 드러나므로 가독성이 향상된다.
3. 함수를 만드는 과정없이 한번에 처리할 수 있기에 코딩하는 시간이 줄어든다.
4. 병렬프로그래밍이 용이하다.
람다식 단점
1. 람다를 사용하면서 만드는 익명함수는 재사용이 불가능하다.
2. 디버깅이 다소 까다롭다.
3. 람다를 남발하면 코드가 지저분해질 수 있다.
4. 재귀로 만들경우에는 다소 부적합한면이 있다.
@FunctionalInterface
interface MyFunction {
// 함수형 인터페이스 : 단 하나의 추상 메소드만 선언된 인터페이스
int max(int a, int b); // public abstract 생략
}
public class LambdaEX1 {
public static void main(String[] args) {
// 람다식(익명 객체)을 다루기 위한 참조변수의 타입은 함수형 인터페이스로 한다.
MyFunction f = (a, b) -> a > b ? a : b;
int value = f.max(3,5);
System.out.println(value);
}
}
|
@FunctionalInterface
interface MyFunctionalInterface{
// 함수형 인터페이스 : 단 하나의 추상 메소드만 선언된 인터페이스
void method();
}
public class LambdaEX2 {
public static void main(String[] args) {
MyFunctionalInterface fi1 = new MyFunctionalInterface() {
@Override
public void method() {
String str = "직접 익명 객체 구현함";
System.out.println(str);
}
};
fi1.method();
MyFunctionalInterface fi2 = () -> {
String str = "람다식 익명 객체 구현함";
System.out.println(str);
};
fi2.method();
}
}
|
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@FunctionalInterface
interface MyFunctionIF {
// 함수형 인터페이스 : 단 하나의 추상 메소드만 선언된 인터페이스
int max(int a, int b); // public abstract 생략
}
public class LambdaEX1 {
public static void main(String[] args) {
// 람다식(익명 객체)을 다루기 위한 참조변수의 타입은 함수형 인터페이스로 한다.
MyFunctionIF f = (a, b) -> a > b ? a : b;
int value = f.max(3,5);
System.out.println(value);
int result = Integer.parseInt("123");
System.out.println(result);
System.out.println("===================================");
ArrayList<Integer> list = new ArrayList<>();
for(int i=0;i < 20;i++)
list.add(i);
System.out.println(list);
// list의 모든 요소를 출력
list.forEach(i->System.out.print(i + ", "));
System.out.println();
// list에서 2 또는 3의 배수를 제거한다.
list.removeIf(x -> x%2==0 || x%3==0);
System.out.println(list);
list.replaceAll(i->i*3); // list의 각 요소에 3을 곱한다.
System.out.println(list);
System.out.println("===================================");
Map<String, String> map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
map.put("3", "3");
map.put("4", "4");
// map의 모든 요소를 {k,v}의 형식으로 출력한다.
map.forEach((k,v)-> System.out.print("{"+k+","+v+"},"));
System.out.println();
}
}
|
메소드 레퍼런스(Method Reference)는 Lambda 표현식을 더 간단하게 표현하는 방법이다.
메소드 레퍼런스는 ClassName::MethodName 형식으로 입력한다.
메소드를 호출하는 것이지만 괄호()는 써주지 않고 생략한다.
import java.util.Arrays;
import java.util.List;
import java.util.function.BinaryOperator;
import java.util.function.IntBinaryOperator;
class MathBox {
// 클래스::메소드 --> 정적(static) 메소드 참조
public static int staticPlus(int x, int y){
return x+y;
}
// 참조변수::메소드 --> 인스턴스 메소드 참조
public int sum(int x, int y){
return x+y;
}
// 정수 빼기
public int sub(int x, int y){
return x-y;
}
// 정수 나누기
public int division(int x, int y){
return x / y;
}
// 실수 나누기
public Float float_div(Float x, Float y){
return x / y;
}
}
public class Method_References {
public static void main(String[] args) {
List<String> strList = Arrays.asList("안녕", "하세요");
strList.stream().forEach(System.out::println);
// static 메소드 참조
IntBinaryOperator operator1;
// 메소드 참조해서 매개변수 리턴타입 알아내 람다식에서 불필요한 매개변수 제거 목적
operator1 = MathBox::staticPlus; // 메소드 참조
System.out.println(operator1.applyAsInt(5, 3));
operator1 = (x, y) -> MathBox.staticPlus(x, y);
System.out.println(operator1.applyAsInt(3, 5));
// instance 메소드 참조
MathBox calculator = new MathBox();
IntBinaryOperator operator2 = calculator::sum; // 메소드 참조
System.out.println("더하기 : " + operator2.applyAsInt(11, 32));
operator1 = (x, y) -> calculator.sum(x, y);
System.out.println(operator1.applyAsInt(11, 32));
operator2 = calculator::sub; // 메소드 참조
System.out.println("빼기 : " + operator2.applyAsInt(11, 30));
operator2 = calculator::division; // 메소드 참조
System.out.println("나누기 : " + operator2.applyAsInt(15, 4));
BinaryOperator<Integer> operator3 = (n1, n2) -> n1 + n2; // 타입 추론
Integer sum = operator3.apply(10, 100);
System.out.println(sum);
BinaryOperator<Float> operator4 = calculator::float_div;
System.out.println("나누기 : " + operator4.apply(15.0f, 4.0f));
BinaryOperator<Float> operator5 = (n1, n2) -> n1 / n2; // 타입 추론
Float div = operator5.apply(15.0f, 4.0f);
System.out.println(div);
}
}
|
자바에서 제공하는 함수형 인터페이스를 이용하면 인터페이스를 만들지 않고 간단하게 코드 구현 가능하다.
import java.util.function.Consumer;
interface Printable {
void doSomething(String text);
}
public class MethodReferencesEX2 {
public static class Printer {
static void printSomething(String text) {
System.out.println(text);
}
}
public static void main(String[] args) {
Printable printable = text -> Printer.printSomething(text);
printable.doSomething("do something");
Printable printable2 = Printer::printSomething;
printable2.doSomething("do something");
// Consumer<클래스>는 자바에서 제공하는 함수형 인터페이스
// String 1개를 인자로 받아 void를 리턴하는 메소드를 갖고 있는 인터페이스
Consumer<String> consumer = Printer::printSomething;
consumer.accept("do something"); // Printable 인터페이스를 만들 필요가 없다.
}
}
|
[Java] HashSet 예제 (0) | 2020.12.12 |
---|---|
Java 와 C/C++ 비교 (0) | 2020.11.08 |
[Java] 다형성 : 참조변수 형변환, 매개변수 다형성 (0) | 2020.07.08 |
[Java] 접근 제어자(access modifier) (0) | 2020.07.08 |
Java Thread synchronized (동기화) (0) | 2019.11.09 |
Retrofit2 라이브러리 Java 버전 코딩을 Kotlin 으로 변환해서 이용하는 법을 적어둔다.
Android Studio 에서 Java 파일 Kotlin 파일로 변환하는 기능을 이용하여 변환하고 나서 에러가 나는 부분을 수정하면 대부분 해결이 된다.
static 은 object 파일로 변환을 해버리는데, 여기서는 companion object 를 사용해서 수동 변환을 했다.
public class RetrofitAPI { |
class RetrofitAPI { |
public interface RemoteService {// 서버에 호출할 메소드를 선언하는 인터페이스 |
interface RemoteService { // 서버에 호출할 메소드를 선언하는 인터페이스 |
로그인 예제 변환
void AutoLoginProgress() { // 자동 로그인 체크 검사 |
fun AutoLoginProgress() { // 자동 로그인 체크 검사 |
Retrofit : PDF 파일 다운로드 및 Viewer 처리 (0) | 2022.08.05 |
---|---|
안드로이드 연동 로그인 PHP JSON 예제 (0) | 2020.09.08 |
Retrofit2 ArrayList 데이터 처리 (0) | 2020.07.14 |
Volley 라이브러리 + Gson 라이브러리 변경 실습 (0) | 2020.07.12 |
Volley 라이브러를 이용한 서버 데이터 가져오기 실습 (0) | 2020.07.12 |
앱을 만들다보면 앱을 실행하면서 현재 위치 좌표값만 획득하고 싶을 경우가 있다.
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" /> |
앱 build.gradle
dependencies { |
SplashActivity.java
public class SplashActivity extends AppCompatActivity { |
PrefsHelper.java
public class PrefsHelper { |
지도를 띄우지 않은 상태에서 현재 위치 좌표만 얻어지는 걸 확인할 수 있다.
참고하면 좋은 게시글
https://medium.com/@droidbyme/android-turn-on-gps-programmatically-d585cf29c1ef
현재 위치반경 범위 데이터 가져오는 SQL 쿼리 (0) | 2022.02.24 |
---|---|
[코틀린] kakao navi 해시 키 등록방법 (0) | 2021.04.11 |
[코틀린] GroupList 가져오기 (0) | 2020.08.02 |
SlidingContentDrawer 메인화면 구성 및 Naver Map 구현 예제 (0) | 2020.07.15 |
네이버 지도 API 이용 1단계 (0) | 2020.06.12 |
RecyclerviewAdapter 에서 Interface로 Activity 로 값을 넘기는 방법에 대한 코드와 Checkbox 에서 전체 선택/해제를 위해 별도의 RelativeLayout 으로 전체선택, 취소, 전송 등의 버튼을 처리하도록 한다.
구현은 전체를 다 구현한 것이 아니라 핵심사항만 구현했지만, 이 정도로도 좋은 코드라고 본다.
MainActivity.java
public class MainActivity extends AppCompatActivity implements RecyclerViewAdapter.OnItemClickListener { |
RecyclerViewAdapter.java
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> { |
Address_Item.kt
import android.os.Parcelable |
address_item.xml
<?xml version="1.0" encoding="utf-8"?> |
[코틀린] expandable recyclerview 예제 (0) | 2021.06.03 |
---|---|
RecyclerView 역순으로 리스트 출력하기 (0) | 2020.08.05 |
RecyclerViewAdapter 만드는 방법 (0) | 2018.10.05 |
RecyclerView에 여러개의 뷰타입 추가 (0) | 2018.07.30 |
support.v7.widget.CardView (1) | 2018.07.23 |
메인 화면 구성을 위해서 구글에서 Github 검색으로 https://github.com/Whhoesj/sliding-content-drawer 를 하나 찾아서 테스트하고 간단하게 적어둔다.
화면 구성은 위와 같다.
https://link2me.tistory.com/1810 에 Navigation Drawer 구성에 대한 개념이 설명되어 있는데, SlidingContentDrawer 는 아래 Java 코드만 살펴보면 이해될 것이다.
Project build.gradle
allprojects { |
앱 build.gradle
dependencies { |
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> |
strings.xml
<resources> |
Drawer Layout 구성
- Layout 구성을 버전에 맞춰 변경 수정했다.
- 파일을 3개의 파일로 분리 구성했다.
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
MainActivity.java 구현
package com.link2me.android.slidingcontentdrawer; |
MapActivity.java 구현
package com.link2me.android.slidingcontentdrawer; |
지도 처리를 위해서는 Naver Cloud 에 앱패키지명을 등록해야 한다.
테스트에 사용한 파일을 첨부한다.
현재 위치반경 범위 데이터 가져오는 SQL 쿼리 (0) | 2022.02.24 |
---|---|
[코틀린] kakao navi 해시 키 등록방법 (0) | 2021.04.11 |
[코틀린] GroupList 가져오기 (0) | 2020.08.02 |
구글 위치 API 로 현재 위치 좌표 얻기 (0) | 2020.07.18 |
네이버 지도 API 이용 1단계 (0) | 2020.06.12 |
작성일자 : 2020.7.14
Retrofit2 라이브러리를 이용하여 데이터 처리하는 걸 테스트하다가 완전 삽질을 한참 했다.
Array로 전체 데이터를 받아서 처리해야 하는데 그렇게 처리하지 않아서 헤메고 있었다.
Retrofit2 기본 개념은 https://link2me.tistory.com/1806 잘 정리되어 있다.
public interface DataCommAPI { |
@Parcelize |
MainActivity.java
public class MainActivity extends AppCompatActivity { |
통신상태가 성공, 실패 여부를 먼저 확인한 다음에
ArrayList 데이터 전체를 출력하는 걸 처리하는 사항
@Parcelize |
public interface RemoteService { |
private void getServerData() { |
추가 오픈일자 : 2020.9.15일
위 안드로이드 코드와 관련된 PHP 코드
<?php "telNO"=>$row['telNO'],"photo"=>$photo,"checkBoxState"=>false)); |
안드로이드 연동 로그인 PHP JSON 예제 (0) | 2020.09.08 |
---|---|
Retrofit2 자바 -> 코틀린 변환 (0) | 2020.07.25 |
Volley 라이브러리 + Gson 라이브러리 변경 실습 (0) | 2020.07.12 |
Volley 라이브러를 이용한 서버 데이터 가져오기 실습 (0) | 2020.07.12 |
Retrofit 2 라이브러리 사용 예제 (0) | 2020.03.21 |
네이버 지오코더 API 를 이용하여 주소 → 위치좌표를 반환하는 PHP 코드와 네이버 지도상에 마커를 보여주는 Javascript 구현 코드 예제다.
IP주소 및 경로 등록이 되어있어야만 Naver Map 이 화면에 보여지며, Naver Cloud 신청에 대한 사항은 https://link2me.tistory.com/1832 게시글을 참조하면 된다.
주소 → 위치좌표 변환을 위해서는 Naver Cloud 에서 Geocorder API가 신청되어 있어야 한다.
Web 브라우저에 보이기 위해서는 Web Dynamic Map 이 신청되어 있어야 한다.
<?php //error_reporting(0); //error_reporting(E_ALL); //ini_set("display_errors", 1); function getNaverGeocode($addr) { $addr = urlencode($addr); $url = "https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode?query=".$addr; $headers = array(); $headers[] ="X-NCP-APIGW-API-KEY-ID:xz06ez230a"; $headers[] ="X-NCP-APIGW-API-KEY:e0A5km9e7Rh5S9QOkr1TRfa4NW8MaDblKAXcrQXL"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); curl_close($ch); return $result; } $shop_name = "광제당한의원"; $addr = "경기도 안산시 단원구 선부광장1로 56"; $geo = getNaverGeocode($addr); $data = json_decode($geo,1); $map_y_point = $data['addresses'][0]['x']; // x 좌표값과 y좌표값이 바뀌어서 출력됨 $map_x_point = $data['addresses'][0]['y']; $lat = $map_x_point; $lng = $map_y_point; ?> <!DOCTYPE html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta http-equiv="expires" content="0" /> <meta http-equiv="pragma" content="no-cache" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script> <script src="https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=xz06ez230a&submodules=geocoder"></script> </head> <body> <div class="container-fluid text-center"> <div class="row"> <div class="col-md-12"> <div class="content" id="content"> <div id="map" style="width:100%;height:450px;"></div> </div> </div> </div> </div> <script> var lat = "<?php echo $lat;?>"; var lng = "<?php echo $lng;?>"; var shop_name = "<?php echo $shop_name;?>"; var addr = "<?php echo $addr;?>"; var HOME_PATH = window.HOME_PATH || '.'; var map = new naver.maps.Map('map', { useStyleMap: true, center: new naver.maps.LatLng(lat, lng), //지도의 초기 중심 좌표 zoom: 15, //지도의 초기 줌 레벨 minZoom: 7, //지도의 최소 줌 레벨 zoomControlOptions : { //줌 컨트롤의 옵션 position : naver.maps.Position.TOP_RIGHT }, mapTypeControl : true }); // 마커 표시 var marker = new naver.maps.Marker({ position: new naver.maps.LatLng(lat, lng), map: map }); var contentString = [ '<div style="text-align:center;padding-left:15px;padding-right:15px;padding-top:5px;">', ' <h4>'+shop_name+'</h4>', ' <p>'+addr+'<br />', ' </p>', '</div>' ].join(''); var infowindow = new naver.maps.InfoWindow({ content: contentString }); naver.maps.Event.addListener(marker, "click", function(e) { if (infowindow.getMap()) { infowindow.close(); } else { infowindow.open(map, marker); } }); infowindow.open(map, marker); </script> </body> </html> |
참고사이트
https://github.com/navermaps/maps.js/tree/master/examples/map
https://navermaps.github.io/maps.js/docs/tutorial-3-geocoder-geocoding.example.html
https://navermaps.github.io/android-map-sdk/guide-ko/0.html
News API 직접 연동 불가를 해결하는 방법 (0) | 2020.11.09 |
---|---|
SMS OTP 인증 구현(설계) (0) | 2020.09.10 |
PhpSpreadsheet 설치 및 사용예제 (0) | 2020.07.07 |
PHP 스팸방지 캡차 오픈소스 활용 코드 (0) | 2020.03.02 |
전화번호 임시번호로 일괄 변경하기 (0) | 2019.09.21 |
이전 코드 구현에서 Gson 라이브러리를 사용하여 코드를 변경하는 부분이 핵심이다.
package com.link2me.android.recyclerviewjava.model |
package com.link2me.android.recyclerviewjava; |
Retrofit2 자바 -> 코틀린 변환 (0) | 2020.07.25 |
---|---|
Retrofit2 ArrayList 데이터 처리 (0) | 2020.07.14 |
Volley 라이브러를 이용한 서버 데이터 가져오기 실습 (0) | 2020.07.12 |
Retrofit 2 라이브러리 사용 예제 (0) | 2020.03.21 |
Volley 라이브러리 사용 예제 (0) | 2018.09.30 |
오랫만에 서버에 있는 자료를 가져오는 걸 했는데 삽질을 한참이나 했다.
코틀린으로의 변환을 고려하여 앱 build.gradle은 아래와 같이 작성했다.
앱 build.gradle
apply plugin: 'com.android.application' |
모델 작성
- 코틀린으로 코드를 구현했다. Java 와 코틀린 혼용 코딩이 가능하다.
package com.link2me.android.recyclerviewjava.model |
Gson 라이브러리를 사용했는데도 불구하고, 데이터가 반환되지 않는 원인을 찾고자 Retrofit2 라이브러리 대신에 Volley 라이브러리를 사용해서 테스트 했다. 두 라이브러리는 동시에 사용할 수가 없더라.
그래서 먼저 Gson 라이브러리 사용없이 for문으로 데이터를 저장하는 걸 시도했다.
package com.link2me.android.recyclerviewjava; |
다른코드는 첨부파일을 참조하면 된다.
Retrofit2 ArrayList 데이터 처리 (0) | 2020.07.14 |
---|---|
Volley 라이브러리 + Gson 라이브러리 변경 실습 (0) | 2020.07.12 |
Retrofit 2 라이브러리 사용 예제 (0) | 2020.03.21 |
Volley 라이브러리 사용 예제 (0) | 2018.09.30 |
AsyncTask return 결과 처리하는 방법 (0) | 2018.08.29 |
Floating Action Button 은 화면에 떠있는 버튼으로 머터리얼 디자인에서 자주 사용하는 기본 위젯이다.
https://www.youtube.com/watch?v=cASXtRa6yDc 동영상을 보면 이해될 것이다.
앱 build.gradle 추가사항
dependencies {
implementation 'com.google.android.material:material:1.1.0'
}
ConstraintLayout 의 모든 보기에는 가로 및 세로 제약조건을 각각 하나 이상 추가해야 한다.
아래 그림에서 ConstraintLayout 에서 버튼의 위치를 결정하는 것은 1번과 2번이다.
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
5번을 누르면 floating 버튼의 색상을 쉽게 변경할 수 있다.
6번은 floating 버튼 안의 이미지를 작성하는 것이다.
Vector Drawable을 사용하고 롤리팝 미만의 기기를 지원해야 할 때는 src 대신에 srcCompat 속성을 사용해야 한다.
검색으로 원하는 이미지를 찾아도 된다.
이름이 자동으로 추가된 것을 확인할 수 있다.
<?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"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"/> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fabMain" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:backgroundTint="#00BCD4" android:tooltipText="메시지 전송" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:srcCompat="@drawable/ic_baseline_menu_24" tools:ignore="MissingConstraints" /> </androidx.constraintlayout.widget.ConstraintLayout> |
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FloatingActionButton fab = findViewById(R.id.fabMain); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view,"실제 클릭 이벤트를 대신 보여준다.",Snackbar.LENGTH_LONG) .setAction("Action",null) .show(); } }); } } |
테스트 파일 첨부 (Java 기반 코드인데 코틀린으로 변환 목적으로 앱 build.gradle이 코틀린 관련 추가되어 있음)
코틀린으로 코드를 변환해보자.
자동변환 전후 Java코드와 kotlin 코드를 보자.
FloatingActionButton fab = findViewById(R.id.fabMain); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view,"실제 클릭 이벤트를 대신 보여준다.",Snackbar.LENGTH_LONG) .setAction("Action",null) .show(); } }); |
val fab = findViewById<FloatingActionButton>(R.id.fabMain) fab.setOnClickListener { view -> Snackbar.make(view, "실제 클릭 이벤트를 대신 보여준다.", Snackbar.LENGTH_LONG) .setAction("Action", null) .show() } |
코틀린 코드를 좀 더 정리하면....
fabMain.setOnClickListener { view -> Snackbar.make(view, "실제 클릭 이벤트를 대신 보여준다.", Snackbar.LENGTH_LONG) .setAction("Action", null) .show() } |
SMS authentication with OTP Layout Example (0) | 2020.09.14 |
---|---|
EditText DatePicker (0) | 2020.08.18 |
CardView Layout 예제 (0) | 2020.04.12 |
Meterial Design 로그인 Layout 예제 (0) | 2020.03.21 |
ScrollView (0) | 2019.12.20 |
- 같은 타입이지만 실행 결과가 다양한 객체 대입 가능한 성질
- 조상 타입의 참조변수로 자손 타입의 객체를 다룰 수 있는 것이 다형성
예제1)
public class Ex7_7 { public static void main(String[] args) { // 조상타입의 참조변수로 자손타입의 객체를 다룰 수 있는 것이 다형성 // 반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수는 없다. Car car = null; // 조상 타입의 참조변수 FireEngine fe = new FireEngine(); // 실제 인스턴스가 무엇인지가 중요 car = fe; // 자손 → 조상으로 형변환. 형변환 생략됨 car.drive(); FireEngine fe2 = null; // 자손 타입의 참조변수 fe2 = (FireEngine) car; // 조상 → 자손으로 형변환. 형변환 생략불가. fe2.drive(); fe2.water(); } } class Car { String color; int door; void drive() { System.out.println("운전중!"); } void stop() { System.out.println("정지."); } } class FireEngine extends Car { void water() { System.out.println("물 뿌리는 중!"); } } |
예제1은 문제없이 잘 동작된다.
예제2는 자손 타입의 참조변수로 조상 타입의 인스턴스를 참조할 수 없다는 사항에 위배된다.
예제2)
public class Ex7_7 { public static void main(String[] args) { // 조상타입의 참조변수로 자손타입의 객체를 다룰 수 있는 것이 다형성 // 반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수는 없다. Car car = new Car(); // 조상 인스턴스 FireEngine fe = (FireEngine) car; // Car cannot be cast to FireEngine fe.drive(); } } class Car { String color; int door; void drive() { System.out.println("운전중!"); } void stop() { System.out.println("정지."); } } class FireEngine extends Car { void water() { System.out.println("물 뿌리는 중!"); } } |
예제3)
public class Polymorphism {
public static void main(String[] args) {
// 조상타입의 참조변수로 자손타입의 객체를 다룰 수 있는 것이 다형성
// 반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수는 없다.
Car car = null; // 조상 타입의 참조변수
FireEngine fe = new FireEngine(); // 실제 인스턴스가 무엇인지가 중요
car = fe; // 자손 → 조상으로 형변환. 형변환 생략됨
car.drive(); // 부모 타입에 선언된 변수와 메소드만 사용 가능
FireEngine fe2 = null; // 자손 타입의 참조변수
if(car instanceof FireEngine){ // 먼저 자식 타입인지 확인 후 강제 타입 실행.
System.out.println("===== 객체 타입 확인 =====");
fe2 = (FireEngine) car; // 조상 → 자손으로 형변환. 형변환 생략불가
fe2.drive();
fe2.water(); // 자식 타입에 선언된 변수와 메소드를 다시 사용해야 하는 경우
}
Car car1 = new FireEngine(); // 부모 클래스 변수 = 자식 클래스 타입;
car1.drive(); // 변환 후에는 부모 클래스 멤버만 접근 가능
System.out.println("===== 상속 처리 =====");
FireEngine fe3 = new FireEngine();
fe3.drive();
fe3.water();
System.out.println("===== 부모 타입 =====");
Car car2 = new Car();
// 자식타입의 참조변수로 부모타입의 인스턴스를 참조할 수는 없다.
FireEngine fe4 = (FireEngine) car2;
fe4.drive();
}
}
class Car {
String color;
int door;
void drive() {
System.out.println("운전중!");
}
void stop() {
System.out.println("정지.");
}
}
class FireEngine extends Car {
void water() {
System.out.println("물 뿌리는 중!");
}
}
|
예제4)
상위클래스 타입의 변수가 복수의 하위클래스 객체를 참조할 수 있도록 하는 것을 다형성이라 한다.
- Product 가 상위 클래스, Tv, Computer, Audio 는 하위 클래스
import java.util.ArrayList;
class Product {
int price; // 제품의 가격
int bonusPoint; // 제품구매 시 제공하는 보너스점수
public Product(int price) {
this.price = price;
this.bonusPoint = (int)(price / 10.0);
}
public Product() {
}
}
class Tv extends Product {
public Tv() {
// 조상 클래스의 생성자 Product(int price)를 호출.
super(100);
}
@Override
public String toString(){
// Object 클래스의 toString()을 오버라이딩한다.
return "Tv";
}
}
class Computer extends Product {
public Computer() {
// 조상 클래스의 생성자 Product(int price)를 호출.
super(200);
}
@Override
public String toString() {
// Object 클래스의 toString()을 오버라이딩한다.
return "Computer";
}
}
class Audio extends Product {
public Audio() {
// 조상 클래스의 생성자 Product(int price)를 호출.
super(50);
}
@Override
public String toString() {
// Object 클래스의 toString()을 오버라이딩한다.
return "Audio";
}
}
class Buyer {
int money = 1000; // 소유금액
int bonusPoint = 0; // 보너스점수
ArrayList<Product> cart = new ArrayList<>();// 구입한 제품을 저장하기 위한 배열
void buy(Product p) { // 매개 변수가 Product 타입의 참조변수
if(money < p.price) {
System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
return;
}
money -= p.price; // 가진 돈에서 구입한 제품의 가격을 뺀다.
bonusPoint += p.bonusPoint; // 제품의 보너스 점수를 추가한다.
cart.add(p); // 제품을 ArrayList<Product> cart에 추가한다.
System.out.print(p + "를 구입하셨습니다.");
System.out.println("현재 잔액은 " + money + " 만원입니다.");
}
void summary() { // 구매한 물품에 대한 정보를 요약해서 보여 준다.
int sum = 0; // 구입한 물품의 가격합계
String itemList =""; // 구입한 물품목록
// 반복문을 이용해서 구입한 물품의 총 가격과 목록을 만든다.
for(int i=0; i < cart.size();i++) {
sum += cart.get(i).price;
if(i == cart.size() -1){
itemList += cart.get(i) + " ";
} else {
itemList += cart.get(i) + ", ";
}
}
System.out.println("구입하신 물품의 총 금액은 " + sum + "만원입니다.");
System.out.println("구입하신 제품은 " + itemList + "입니다.");
}
}
public class Ploymorphism {
public static void main(String[] args) {
Buyer b = new Buyer();
b.buy(new Tv());
b.buy(new Computer());
b.buy(new Audio());
b.summary();
}
}
|
Java 와 C/C++ 비교 (0) | 2020.11.08 |
---|---|
[Java] 람다식(Lambda Expression) (0) | 2020.07.26 |
[Java] 접근 제어자(access modifier) (0) | 2020.07.08 |
Java Thread synchronized (동기화) (0) | 2019.11.09 |
Java Thread 상태 제어 - 안전한 종료 (0) | 2019.11.08 |
패키지의 선언
- 패키지는
소스파일의 첫 번째 문장으로 단 한번 선언
- 같은
소스 파일의 클래스들은 모두 같은 패키지에 속하게 된다.
- 패키지
선언이 없으면,
이름없는
패키지에 속하게 된다.
- 패키지명은 선언시 반드시 소문자로 선언해야 한다.
import문
- 클래스를
사용할 때 패키지 이름을 생략할 수 있다.
- 컴파일러에게
클래스가 속한 패키지를 알려준다.
- java.lang
패키지의
클래스는 import
하지
않고도 사용할 수 있다.
- import문은
패키지문과 클래스 선언의 사이에 선언한다.
접근 제어자
제어자 |
같은 클래스 |
같은 패키지 |
자손 클래스 |
전체 |
public |
○ |
○ |
○ |
○ |
protected |
○ |
○ |
○ |
|
(default) |
○ |
○ |
|
|
private |
○ |
|
|
|
아래 코드는 Eclipse 툴이 아니라 Android Studio 에서 Android 어플 작성을 위한 코드 생성으로 테스트했다.
개념은 동일하므로 Eclipse, Android Studio 상관 없다.
package com.link2me.android.pkg1; |
package com.link2me.android.pkg2; |
[Java] 람다식(Lambda Expression) (0) | 2020.07.26 |
---|---|
[Java] 다형성 : 참조변수 형변환, 매개변수 다형성 (0) | 2020.07.08 |
Java Thread synchronized (동기화) (0) | 2019.11.09 |
Java Thread 상태 제어 - 안전한 종료 (0) | 2019.11.08 |
Java Thread 이해 및 Thread Life Cycle (0) | 2019.11.07 |
PHPExcel 이 deprecated 되어 PHP 7.2 이상에서 지원이 안되므로 PHPSpreadsheet 를 설치해야 한다.
이용환경 : CentOS 7
PHP 7.3 yum 설치 스크립트 : https://link2me.tistory.com/1841 참조
설치 방법
- 윈도우 환경에서는 https://getcomposer.org/download/ 에서 설치 파일을 다운로드 하는 거 같다.
- 리눅스 설치 환경에서는 composor 가 설치되어 있어야 한다.
https://zetawiki.com/wiki/%EB%A6%AC%EB%88%85%EC%8A%A4_composer_%EC%84%A4%EC%B9%98
에 나온 방법대로 설치를 한다.
먼저 vi /etc/php.ini 에서 allow_url_fopen = On 이 되어 있어야 아래 코드가 동작된다.
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
composer -V
export COMPOSER_ALLOW_SUPERUSER=1
composer -V
echo "export COMPOSER_ALLOW_SUPERUSER=1" >> ~/.bashrc
cat ~/.bashrc | grep export
이제 PhpSpreadsheet 의 설치는 PHP가 설치된 경로에서 한다.
cd /var/www/html/
composer require phpoffice/phpspreadsheet
실 사용 예제
기존 PHPExcel 라이브러리를 이용하여 사용하던 코드에서 변경할 부분만 변경해서 사용하면 된다.
<?php |
이제 PHPSpreadsheet 라이브러리를 이용한 코드 예제를 보면 변경된 부분이 뭔지 알 수 있다.
<?php |
SMS OTP 인증 구현(설계) (0) | 2020.09.10 |
---|---|
PHP 네이버 주소 좌표변환 및 Web 지도 표시 예제 (0) | 2020.07.13 |
PHP 스팸방지 캡차 오픈소스 활용 코드 (0) | 2020.03.02 |
전화번호 임시번호로 일괄 변경하기 (0) | 2019.09.21 |
preg_replace_callback를 이용한 문자열 치환 (0) | 2019.09.15 |
CentOS 7 에서 Apache 와 PHP 7.3 yum 설치하고 MariaDB 10.3 을 yum 설치하는 스크립트를 적어둔다.
################################ |
############################################# |
CentOS7 PHP-FPM yum 설치 (0) | 2020.09.16 |
---|---|
MariaDB 깨졌을 때 복구 및 백업 (0) | 2020.09.02 |
[Apache] Reverse Proxy Setting on CentOS 7 (0) | 2020.07.03 |
CentOS 7/6 기반 PHP 3 Tier 구조 만들기 (0) | 2020.06.28 |
CentOS6 에 Apache + PHP 5.6 + MySQL 5.6 소스 설치 (0) | 2020.06.14 |
개발툴 설치를 기본으로 설치하지 않고 내가 원하는 디렉토리를 지정하여 설치할 수 있다.
이렇게 필요한 것을 설치하면 된다.
OpenJDK 설치 (0) | 2020.11.08 |
---|---|
Android Debugging Stetho 사용 (SQLiteDB Viewer) (0) | 2020.09.10 |
[코틀린] Anko 라이브러리 추가 방법 (0) | 2020.04.20 |
자바와 코틀린 함께 사용하기 (0) | 2020.03.22 |
Android NDK 사용을 위한 설정 (0) | 2019.12.06 |
이번에 구성해 본 건 위 그림의 1번 설정 내역이다.
Apache 서버에서 Reverse Proxy를 설정하여 사설망 PHP-FPM이 설정된 서버로 포워딩을 해서 처리한다.
포트를 9000 번으로 변경해서 테스트를 해보고 싶은데 PHP-FPM 설정 방법을 완벽하게 이해하지 못했다.
설정을 제대로 이해하고 한 것인지는 모르겠는데 동작은 이상없이 잘 된다는 건 확인했다.
##################################### #Step 3 Virtual Host 설정 # Reverse Proxy : 외부에서 접속했을 때 내부서버나 다른 곳으로 연결해 주는 방법 |
인터넷망에서 사용할 수 없는 IP 대역이
10.X.X.X
172.16.X.X
192.168.X.X
이다.
사설망 접속은 NAT(Network Address Translation) 처리를 해주는 장치가 있어야 한다.
IP Time 공유기, Router, Switch, 방화벽 등이 이런 기능을 수행한다.
MariaDB 깨졌을 때 복구 및 백업 (0) | 2020.09.02 |
---|---|
CentOS 7 Apache + PHP 7.3 + MariaDB 10.3 yum 설치 (0) | 2020.07.07 |
CentOS 7/6 기반 PHP 3 Tier 구조 만들기 (0) | 2020.06.28 |
CentOS6 에 Apache + PHP 5.6 + MySQL 5.6 소스 설치 (0) | 2020.06.14 |
[CentOS 6] hosts 변경 (0) | 2020.03.03 |