본문 바로가기

수업 정리

69일차 수업정리(Lambda, Android Interface)

**클래스나 인터페이스 사용

    => 안드로이드에서는 이벤트 처리를 할 때 내부 클래스나 내부 인터페이스를 자주 사용

    => 대부분 이벤트가 발생할 때만 이 클래스의 객체를 이용하므로 별도 클래스 생성없이 사용하는 경우가 많음

    => 메소드가 1개 뿐인 인터페이스 사용시 JDK1.7 버전 부터는 람다 문법을 지원

    => 자바에서 상속하는 방법

        (1) 클래스를 상속받거나 인터페이스를 구현한 별도의 클래스를 만들어서 사용

        (2) Anonymous Class를 이용하는 방법

        (3) 메소드가 1개인 인터페이스를 이용할 때는 람다를 이용하는 것이 가능

 

**람다

    => JDK 1.7 버전에서 함수형 프로그래밍을 지원하기 위하여 도입

    => Java는 완전한 객체 지향 언어이므로 함수라는 것이 존재하지 않음

        - 모든 것은 전부 객체를 생성하여 사용

    => Big Data 처리 시스템에 특정한 작업만 수행시켜 데이터를 처리해야함. Java는 객체단위 제공으로 무거워서 함수형 프로그래밍 도입

        - Scala, Kotlin등의 언어들이 Java의 문법을 그대로 사용할 수 있는 상태에서 함수형 프로그래밍을 도입

    => Android Studio가 메소드가 1개 뿐인 내부 인터페이스를 anonymous로 만들면 코드 최적화를 통해 람다식으로 변경

함수(Function) 메소드(Method)
- 아무곳에서나 이름만 가지고 호출이 가능 - 자신의 클래스 내부에서는 이름만으로 호출 가능
- 외부에서는 반드시 호출하는 주체가 있어야 호출 가능
  (receiver : Class 또는 Instance)

    => 람다 작성 방법 : (자료형 매개변수, ...) -> {실행할 문장;}

        - 매개변수 자료형은 생략 가능 - 실행 할 때 대입되는 매개변수를 가지고 자료형을 판단

        - 매개변수가 1개인 경우는 () 생략 가능

        - 실행할 문장이 하나이면 {} 생략 가능

        - return 하고자 하면 return 뒤에 리턴할 내용 작성

 

**Thread

    => 비동기적으로 작업을 처리할 수 있도록 해주는 작업 단위

    => Web Programming에서는 거의 직접 생성하지 않고 대부분 WAS가 알아서 생성하여 수행

    => Android와 같은 Application Programming에서는 직접 생성해야 하므로 중요

 

**Web Programming 방식

    => CGI(Common Gateway Interface) : 사용자의 요청을 하나의 프로세스로 처리하는 방식으로 perl이 대표적

    => Application Server : 사용자의 요청을 하나의 스레드로 처리하는 방식으로 jsp(java), asp.new(C#), php등이 대표적

 

**Runnable 인터페이스

    => 스레드를 만들어 주는 인터페이스

    => 소유하고 있는 메소드는 public void run() 1개

        - 이 메소드에 스레드로 수행할 내용을 작성

    => 인터페이스를 구현한 인스턴스를 Thread 클래스의 생성자에 대입, Thread 인스턴스 생성, start() 호출시 스레드가 생성되어 시작

 

**람다 실습

1. 외부에 별도의 클래스를 만들어 사용

    => 가독성이 좋고 유지보수에 유리

    => 데이터 공유가 어려움 : 생성자, setter메소드를 이용하여 데이터 공유

  1) Runnable 인터페이스를 implement한 클래스를 생성

public class RunnableImpl implements Runnable {
	@Override
	public void run() {
		try {
			for( int i=0; i<10; i+=1) {
				Thread.sleep(1000);
			}
		}catch(Exception e) {
			System.out.println(e.getMessage());
		}
	}
}

 

  2) main 메소드에서 스레드를 생성하여 실행

public static void main(String[] args) {
	//별도의 클래스를 만들어서 스레드를 사
	Thread th1 = new Thread(new RunnableImpl());
	th1.start();
}

 

2. 1번에서 만든 클래스를 외부에 생성하지 않고 클래스 내부에 만들어서 사용

    => 1번에서 만든 클래스를 다른 클래스에서 전혀 사용할 필요가 없다면 내부 클래스로 만드는 것이 효율적

    => Android는 이벤트 처리 리스너를 전부 내부 인터페이스로 정의, ClieckListrener의 경우 View외에서 사용불필요, ClieckListener는

       View클래스의 내부 인터페이스로 생성되어 있음

 

3. Anonymous Class(익명 클래스)

    => 클래스를 만들지 않고 바로 인스턴스를 만들어서 사용하는 방식

        - new 상위클래스나 인터페이스명(매개변수){  필요내용 작성  }

    => main 메소드에 추가

//anonymous class를 이용하는 방법
new Thread(new Runnable() {
	@Override
	public void run() {
		try {
			for(int i=0; i<10; i+=1) {
				Thread.sleep(1000);
				System.out.println("익명클래스 사");
			}
		}catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
}).start();

 

4. 람다 사용

new Thread(()->{
	try {
		for(int i=0; i<10; i+=1) {
			Thread.sleep(1000);
			System.out.println("람다이용");
		}
	}catch (Exception e) {
		System.out.println(e.getMessage());
	}
}).start();

 

**View Architecture

    => View 안에 다른 View를 배치하는 것이 가능

    => 포함하고 있는 View를 일반적으로 Super View라고 하고 포함된 view를 sub View라고 하는 경우가 많음

    => View를 포함하는 View는 대부분 ViewGroup으로 만들고 포함된 View는 ViewGroup, widjet등으로 생성

    => XML에서 만들 경우 sub View를 super View의 하위 태그로 추가

    => Java로 만들 때는 super view가 addView(subview 객체)를 호출해서 추가

 

**TextView

    => 문자열을 출력할 수 있는 View

    => Button과 EditText(문자열 입력이 가능한 View)의 상위 클래스

1. text

    => 출력할 문자열을 설정하는 속 성

 

2. 문자열 사용

    => 안드로이드에서는 문자열 상수를 등록할 수 있는 String.xml파일을 제공

    => 생성할 때는 <string name="구별할 이름">내용</string>으로 생성하고 xml에서 사용할 때는 @string/이름으로 사용

 

3. string.xml 파일에 문자열을 등록하고 TextView를 이용하여 출력하고 출력된 내용을 로그로 출력

  1) string.xml 파일에 문자열을 등록

<string name="creed">
    학을 해야 습을 할 수 있고, 습을해야 지 할수 있다.
</string>

 

  2) layout 파일을 수정

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/creed"
    android:id="@+id/txtcreed"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

 

  3) Activity.java 파일의 onCreate 메소드를 수정

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Activity의 MainView를 설정하는 문장
    setContentView(R.layout.activity_main);
    //xml 파일에 만든 view를 찾아오기
    TextView txtCreed = findViewById(R.id.txtcreed);
    //CharSequence는 String의 상위 인터페이스
    txtCreed.setText("이건 됩니다.");
    //텍스트를 가져올 때 Android에서는 toString()을 호출하여 가져옴
    String creed = txtCreed.getText().toString();

    //로그 출력
    Log.e("삶의 신조", creed);
}

 

4. autoLink

    => 내용을 해석해서 자동으로 링크를 만들어 주는 속성

        - none : 링크를 지원하지 않음

        - web : URL로 인식해서 클릭하면 chrome이 열게 됨

        - email : 이메일로 인식해서 Mail 앱이 실행됨

        - phone : 전화번호로 인식

        - map : 지도의 주소로 인식

        - all : 위의 모든 것을 전부 인식

    => 2개 이상의 조합이 가능

    => 옵션은 대부분 정수로 생성 - 값을 제한하고자 하는 경우 enum 사용

        - 정수의 값이 일련번호처럼 이어지는 번호이면 중복 사용이 불가능한 것이고, 2의 지수승형태의 경우 중복사용 가능

        - 중복사용시 |(or)로 결합

        - web과 email을 같이 사용하고자 하면 web | email

 

**EditText

    =>포커스를 가질수 있는 TextView의 하위 클래스

    => Focus(iOS에서는 FirstResponder)를 가질수 있으면 키보드를 이용할 수 있음

        - 이 클래스의 인스턴스가 포커스를 받으면 화면에 키보드가 출력되고 포커스를 잃으면 키보드가 사라짐

1. inputType

    => 입력할 수 있는 종류는 설정하는 속성

    => 이 속성에 의해서 키보드의 종류가 결정되고 중복 사용 가능

 

2. 문자열 변경 리스너

    => 입력하는 문자열이 변경될 때 호출되는 메소드를 소유한 리스너

    => addTextChangedListener(TextWatcher watcher) 메소드를 이용해서 등록

        - TextWatcher는 여러개의 메소드를 소유하고 있음(람다 사용 불가)

 

3. 글자 수 제한

    => SetFilters(InputFilter[] filters)

 

4. 키보드 관리

    => InputMethodManager 클래스의 객체가 수행

  1) 화면에 키보드 출력

    - showSoftInput(View view, int flags) : View는 키보드를 눌렀을 때 입력될 View

  2) 화면에서 키보드를 제거

    - hideSoftInputFromWindow(IBinder windowToken, int flags, ResultReceiver resultReceiver)

    => 입력이 끝나면 키보드를 화면에서 제거해야 함

        - 엔터키를 누를때, 일정 글자 수를 입력했을 때, 화면의 빈 영역을 터치했을 때 등 적절한 이벤트에서 키보드를 제거해 주어야 함

    => 키보드가 화면에서 출력할 때나 화면에서 사라질때 UI를 변경하는 부분도 생각해야 함

 

5. EditText 실습

  1) 실행가능한 Activity 추가 : 실행가능하다는 것은 첫 화면이 될수 있다는 의미

 

  2) 레이아웃 파일에 화면 디자인

<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"
    tools:context=".EditText"
    android:orientation="vertical">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/edit"
        android:inputType="textEmailAddress"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/text"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btnshow"
        android:text="키보드 보이기"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btnhide"
        android:text="키보드 숨기기"/>

</LinearLayout>

 

  3) Activity 파일에서 사용할 인스턴스 변수 선언

    => EditText, TextView, Button 2개

//뷰 변수
EditText edit;
TextView text;
Button btnShow;
Button btnHide;

 

  4) Activity 파일의 onCreate 메소드에서 레이아웃에 정의한 뷰를 찾아 인스턴스에 대입

//뷰 객체 찾아오기
edit = (EditText)findViewById(R.id.edit);
text = (TextView)findViewById(R.id.text);
btnShow = (Button)findViewById(R.id.btnshow);
btnHide = (Button)findViewById(R.id.btnhide);

 

  5) edit에 글자를 입력하면 입력이 끝남과 동시에 text에 출력

    => onCreate 하단에 추가

//edit에 문자열이 변경되면 처리
edit.addTextChangedListener(
       new TextWatcher() {
            //키보드는 눌렀고 누른 키보드의 값을
            //EditText에 표시하기 전
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                //edit의 문자열을 text에 출력
                text.setText(edit.getText());
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });

 

  6) edit에 글자수를 제한

    => onCreate 메소드에 추가

//edit에 입력 제한
edit.setFilters(new InputFilter[]{
       new InputFilter.LengthFilter(3),
       new InputFilter.AllCaps()
});

 

  7) 프로젝트의 자바 버전을 설정

    => [File] - [Project Structure]를 실행하고 [Module]에서 Source와 target을 설정

 

  8) 버튼을 누르면 키보드를 보이게 하고 사라지게 하기

    => onCreate 메소드에 추가

btnShow.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View view){
        //키보드 관리 객체 가져오기
        InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
        //키보드 출력 : 키보드를 누르면 edit에 입력
        imm.showSoftInput(edit, 0);
    }
});

btnHide.setOnClickListener((View view) -> {
    InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(edit.getWindowToken(), 0);
});

 

**ImageView

    => 이미지를 화면에 출력하기 위한 뷰

1. src

    => 출력할 이미지를 설정하는 속성

    => 보통의 경우 res/drawable 디렉토리에 이미지를 복사해두고 @drawable/ID를 이용해서 설정

    => 이미지 파일은 drawable 디렉토리에 복사시 확장자를 제외한 부분이 자동으로 ID로 설정

        - 이름은 같고 확장자가 다른 이미지 파일은 같이 사용할 수 없음

        - 이미지 파일의 일므은 영문 소문자와 숫자만의 조합으로 만들어야 함

 

2. 크기 관련 속성

  1) maxHeight, maxWidth

  2) adjustViewBounds : 이미지가 확대, 축소될 때 이미지의 종횡비를 어떻게 할 것인지를 설정

  3) 해상도에 따른 이미지 설정

    - drawable-mdpi, drawable-hdpi, drawable-xdpi, drawable-xxdpi, drawable-xxxdpi 디렉토리 생성, 이미지 파일을 동일하게 저장

 

3. 이미지 출력 실습

  1) 출력할 이미지 파일을 drawable 디렉토리에 복사

  2) 실행가능한 Activity 추가 

    => 실행가능한 Activity가 아닌 경우 실행가능한 Activity로 변경하기

    => Androidmanifest.xml 파일에서 MainActivity가 등록된 태그의 내용을 복사하면 됨

<intent-filter>
    <action android:name="android.intent.action.MAIN" />

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

 

  3) layout 파일에 화면 디자인

<?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"
    tools:context=".ImageActivity">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@drawable/image1"
        android:maxHeight="100dp"
        android:maxWidth="50dp"
        android:adjustViewBounds="true"
        android:tint="#3300ff00"/>
    
</LinearLayout>

 

**Button

    => TextView 클래스로부터 상속 받음

    => 하위 클래스로 CompoundButton이 있고 다시 상속 받아서 CheckBox, RadioButton, ToggleButton 클래스가 존재

 

**assets와 resoures

    => resource는 작은 크기의 자원을 의미하는 데 res 디렉토리에 저장한 데이터들은 앱이 실행될 때 메모리에 전부 로드가 된 상태

    => assets는 큰 크기의 자원을 의미해서 이 자원들은 사용할 때 메모리에 로드 됨

1. 큰 자원을 저장하기 위한 assets 디렉토리를 생성

    => 패키지명을 선택하고 마우스 오른쪽을 클릭하여 [New] - [Folder] - [Assets Folder]

 

2. 프로젝트에서 사용할 폰트파일을 assets 디렉토리에 복사

 

3. 프로젝트에서 사용할 이미지 파일을 drawable 디렉토리에 복사

    => mask.png

 

4. string.xml 파일에 문자열을 등록

<string name="msg">
    거인의 어깨에 얼라서서 더 넓은 세상을 보라
    내가 알고자 하는 모든 것은 책에 전부 있다.
</string>

5. 실행가능한 Activity를 추가

    => 기존  Activity 사용 가능

 

6. 레이아웃을 수정 : ?.xml

<?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"
    tools:context=".CommonViewActivity">

    <!-- 텍스트 출력 -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="구글 https://www.google.com
        전화번호: 010-0505-2626
        메일 : insa8029@naver.com"
        android:autoLink="web|phone|email"/>

    <!-- 자바에서 동적으로 이용할 것이라면 id를 부여해야 함 -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/msg"
        android:id="@+id/txtmsg"/>
    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/checkbox"
        android:text="체크가 안된 상태"/>
</LinearLayout>

 

7. Activity 파일의 onCreate 메소드를 수정

public class CommonViewActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_common_view);

        //TextView가져오기
        TextView txtmsg = (TextView)findViewById(R.id.txtmsg);
        //assets에 있는 폰트 파일을 이용해서 폰트를 생성
        Typeface tf = Typeface.createFromAsset(getAssets(),
                "NanumGothic.ttf");
        txtmsg.setTypeface(tf);
    }
}

 

**Layout

    => View의 하위 클래스로 화면에 출력되는 대상이지만 자체 UI는 없어서 문자열이나 이미지들을 출력할수 없는 ViewGroup

1. 종류

  1) LinearLayout : 수평이나 수직 방향으로 하위 뷰들을 배치하는 레이아웃

  2) RelativeLayout : 첫번째는 Layout을 기준으로 다음 뷰 부터는 이전 뷰와의 관계로 배치하는 레이아웃

  3) FrameLayout : 모든 하위 뷰를 왼쪽 상단을 기준으로 배치

    - 하위 뷰가 2개 이상이면 겹쳐져서 출력

  4) TableLayout : 모두 동일한 너비와 크기를 갖는 레이아웃

  5) GridLayout : 셀을 합칠수 있는 TableLayout

  6) ConstraintLayout : 제약조건을 가지고 만들어지는 레이아웃

    - 현재 기본 레이아웃

  7) AbsoluteLayout : 모든 하위 뷰들의 좌표와 크기를 설정해서 만드는 레이아웃

    - 현재는 deprecated(사용하지 않는 것을 권장)

 

2. Layout과 유사하게 사용되는 View

  1) Tab Host

 

  2) ScrollView : 화면보다 더 큰 콘텐츠를 배치하고자 할 때 사용

 

  3) ListView 계열의 View

 

**LinearLayout

1. orientation

    => vertical : 수직 방향으로 배치

    => horizontal : 수평 방향으로 배치

 

2. 좌우나 상하 맞춤

    => gravity, layout_gravity

        - gravity : 내용물이 어디에 배치되는 지

        - layout_gravity : 하위 뷰들이 어디에 배치되는지(orientation의 반대 방향만 설정 가능)

    => 값(or로 연산 가능)

center_horizontal 0X01 00000001
left 0X03 00000011
right 0X05 00000101
center_vertiacl 0X10 00010000
top 0X30 00110000
bottom 0X50 01010000
center 0X11 00010001

 

3. layout_weight

    => 비율을 설정

    => 0이면 자신의 고유한 크기만큼, 1이상이면 전체 값을 모두 더한 값의 1/n로 크기 값 설정

 

4. padding, margin

    => 여백

 

5. LinearLayout 연습

    => 실행가능한 Activity 생성

  1) 맞춤 연습 - layout.xml

<?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"
    tools:context=".LinearActivity"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="맞춤 테스트"
        android:textSize="30sp"
        android:textColor="#ff0000"
        android:gravity="center"/>
</LinearLayout>

 

  2) weight 연습 - 비율로 배치

<?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"
tools:context=".LinearActivity"
android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="버튼 1"
        android:textSize="30sp"
        android:textColor="#00ffff"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:text="버튼 2"
        android:textSize="30sp"
        android:textColor="#ff00ff"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:text="버튼 3"
        android:textSize="30sp"
        android:textColor="#0000ff"/>
</LinearLayout>

 

  3) 실습

    => 출력할 이미지를 drawable 디렉토리에 복사

    => layout.xml 파일의 내용을 수정