728x90

Intent

intent: 우편배달부. 의사소통을 책임짐

  • 액티비티와 액티비티 간
  • 앱과 앱 간

 

타입 두 가지

1) 명시적 Intent

- 하나의 앱 내에서 액티비티와 액티비티 간 소통 시 자주.

- 보낸 이와 받는 이가 명시되어 있음

 

Intent intent = new Intent(this, NewActivity.class);

startActivity(intent);

 

보낸 이 : this(현재의 액티비티)

받는 이: NewActivity.class

 


2) 암시적 Intent

- 앱과 앱 간(다른 앱의 활동을 호출하여 원하는 기능을 수행, 웹 브라우저를 열어 특정 페이지를 표시하거나, 연락처 앱을 열어 특정 연락처를 표시하는 등)

- 시스템 서비스 사용: Android 시스템의 여러 서비스를 활용( 이미 안드로이드에 내장되어 있는 기능) 예를 들어, 카메라 앱을 시작하여 사진을 찍는 기능, 위치 서비스를 사용하여 현재 위치를 얻는 기능

- 받는 사람과 보내는 사람이 명시되어있지 않음

 

sendIntent.setAction(Intent.ACTION_CALL);
startActivity(sendIntent);
Intent sendIntent = new Intent();

 


Intent 없는 상태

...

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

	@Override
    protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState); //onCreate는 AppCompatActivity 클래스에 정의된 콜백메서드
    setContentView(R.layout.activity_main);
    
    Button button = (Button) findViewById(R.id.btn_call); //Button은 view에 속한 컴퍼넌트
    button.setOnClickListener(this); //this는 OnClickListener 인터페이스
    
    }
    
    @Override
    publid void onClick(View view) {
    	Toast.makeText(MainActivity.this, "Click!!", Toast.LENGTH_SHORT).show();
        } //여기서 this는 입력받은 매개변수인 view, 즉 클릭된 view의 컴퍼넌트인 button
        //여기서 onClick은 OnClickListener 인터페이스 내부에 정의된 콜백 메서드
        //즉, button이 클릭되면 '클릭되었다'는 것을 OnClickListener가 알아차리고 이에 따라 onClick 콜백 메서드가 실행됨
    }

 

암시적 Intent

...

@Override
public void onClick(View view){

    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_CALL);
    startActivity(intent);
    }
}

 

명시적 Intent

...

@Override
public void onClick(View view) {
    Intent intent = new Intent(MainActivity.this, CallActivity.class); //또다른 자바 클래스 activity를 생성함
    startActivity(intent);
    }
}

 

728x90
728x90

0) 안드로이드의 삼대장&원수 (??)

출처: https://www.youtube.com/watch?v=49N59HnCAxQ&t=109s 

- 원수: Activity !!! : foreground(눈에 보일 때만) 일을 하는 녀석
   액티비티는 곧 화면 (UI를 보여주고 실제 기능까지 한다. 다 한다.)

- 대장 1: ContentProvider: 자료나 데이터 받아오는 경우 (사용하지 않는 경우 있음)

- 대장 2: Service: background(눈에 보이지 않는데) 일을 하는 녀석

- 대장 3: BroadcastReceiver: 알림을 도와주는 녀석 (ex. 카톡 메시지가 왔을 때 '메시지 왔다'는 사실을 알려주는 것.) 콜백과 비슷한 기능.. 통신 느낌.

https://www.youtube.com/watch?v=49N59HnCAxQ&t=109s

1) Activity의 활동 수명

https://developer.android.com/guide/components/activities/activity-lifecycle?hl=ko


2) View: 화면 그 자체

  • Activity에 씌우는 화면 껍데기
  • XML, Java 둘 중 하나로 작성 가능 (보통 XML)
    • xml파일에 <TextView.../> 하는 게 다 여기에 해당
  • 보통 widget, adapter, layout 계열로 나눌 수 있음
    • widget; TextView, ImageView 등. 용도가 뚜렷함.
    • adapter; ListView, GirdView, RecyclerView 등. 여러 개의 많은 정보를 길게 스크롤하여 나열할 때 많이 씀

3) Layout

  • layout; LinerLayout, RelativeLayout, FrameLayout... 화면 공간 배분할 때 많이 쓰임.

4-1) Thread

- 작업의 흐름

- 기본적으로 main / UI thread가 존재함

4-2) Multi threading : 분업

출처: https://www.youtube.com/watch?v=7oeSMTfZ2mo&t=1129s 

https://www.youtube.com/watch?v=7oeSMTfZ2mo&t=1129s

- 단!! 무조건 많을수록 좋은 것은 아니다: 빠른 속도로 다양한 일을 하기에, 동시에 되는 것처럼 착각하는 경향이 있음.

- 일반적인 앱의 경우, main에 1~2개 Thread만 멀티로 두는 편

https://www.youtube.com/watch?v=7oeSMTfZ2mo&t=1129s


https://www.youtube.com/watch?v=7oeSMTfZ2mo&t=1129s

- Thread: java에서 제공하는 클래스

- Handler: android에서 제공하는 클래스

 

방법 1: 자바스러움

1) Thread가 실제 계산/어떤 일을 수행하고 나서. 일을 다 한 내역을 Handler thread에 보내줌

2) Thread로부터 받아온 일 결과물을, Handler를 통해 간접적으로 반영해줌

 

방법 2: AsyncTask

- Android Recommended

- 간단하게 새로운 쓰레드를 생성해서 작업할 수 있음 (코드도 간결)

 

 


https://www.youtube.com/watch?v=LvBNVuXbS3E 

 

728x90
728x90

인터페이스의 쓰임새

*UI(유저 인터페이스) 아님!!!

  • 다중 상속
  • 콜백 메소드

인터페이스의 기능: 1) 다중 상속

1. Java에서는 2개 이상의 상속이 불가능하다

2. '상속(extends)' 대신 '구현(implements)'하자.

3. by '인터페이스'

 

상속 (extends) 구현 (implements)
- 아이덴티티를 보유한다
ex) 개는 동물이다 (개는 동물에 완전히 속하므로)
- 역할(role)을 부여한다
ex) 개는 반려동물이다 (일부 개에게만 해당)

- 구현 implements은 변수를 상속받지 않는다 (오로지 행동 메서드만 취함)

 

 attackable이라는 interface를 만들면 우리가 지정한 대상에 한해서 attack이라는 메소드를 공유할 수 있도록 함

(부모클래스에 attack 포함하면 그것을 상속하는 모든 클래스가 attack할 수 있게 되므로 No)

 

https://www.youtube.com/watch?v=49COMLtdY04

→ sell 파는 것 & upgrade : Trade와 관련된 것들은 서로 공유할 수 있도록 함.

 


인터페이스의 기능: 2) 콜백 함수

Callback

사용자가 버튼을 눌렀을 때(event) 뭔가 하고싶어

- 앱을 사용하다가 홈버튼을 누르면 어떻게 처리하지?

- 다운로드가 완료되었으면 알림을 울릴 수 없을까?

 

콜백 메소드: 이러한 시점(event)에 호출되는 메소드

Q. 어떤 게 콜백이지?

- 콜백 메소드는 보통 onClick, onTouch, onPressed 등 on~이 붙는다.

- 콜백을 정의한 인터페이스는 보통 OnClickListener, OnTouchListener 등 Listener가 붙는다.

https://www.youtube.com/watch?v=IBxiy7dzv_4&t=333s

 

- OnDownloadListener: 인터페이스

- Download(this)의 this는 Downloader 클래스일 수도 있고, OnDownloadListener 인터페이스일 수도 있는데, 실제 Download 함수 정의한 내용에서 매개변수로 오직 OnDownloadListener만을 취하므로, 후자를 가리키게 됨

- Download 함수에서 정의한 코드가 완료되면 listener 인터페이스에 onDownloadFinish()라는 메소드가 실행됨.

- "다운로드라는 이벤트를 완료했어"라는 알림을 onDownloadFinish라는 콜백함수가 listener 인터페이스에게 전달해주는 것임.

- onDownloadFinish 콜백 함수는, 실제로 OnDownloadListener이라는 인터페이스로부터 받아온 (@Override) 함수임.

 



reference: 겜팔이의 안드로이드 세뇌교실

728x90

728x90

이벤트 내용

 

- Count 버튼을 누르면 수를 카운트 하고

- 카운트 한 만큼 화면에 띄우기

- Reset 버튼을 누르면 카운트 값 리셋하기


MainActivity.java

package com.example.cute_tutorial;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private int count = 0;
    private TextView countText;

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

        countText = (TextView) findViewById(R.id.count_text);
        countText.setText("0");
    }

    public void buttonCount(View view) {
        count++;
        if (countText != null) {
            countText.setText(Integer.toString(count));
        }
    }

    public void buttonReset(View view) {
        count = 0;
        if (countText != null) {
            countText.setText(Integer.toString(count));
        }
    }
}

 

private int count = 0;
private TextView countText;

 

Android 개발에서 TextView는 사용자 인터페이스(UI)를 구성하는 데 사용되는 위젯(Widget) 중 하나

- 주요 기능: 텍스트를 화면에 표시 (정적/동적)

 

- 레이아웃 파일(XML) 또는 Java 코드에서 사용됨

(1) XML에서 TextView 위젯 추가

<TextView
    android:id="@+id/myTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello, World!"
    android:textSize="18sp"
    android:textColor="#000000"
    android:gravity="center"
    android:layout_gravity="center"/>

 

(2) Java 코드에서 TextView를 조작하려면, findViewById() 메서드를 사용하여 xml에 정의된 TextView의 id값을 참조하는 방식으로 해당 TextView 객체를 가져오면 됨

- 객체를 가져오기만 하면, 나머지 이벤트는 기본 프로그래밍 방식으로 처리.

 

countText = (TextView) findViewById(R.id.count_text);
countText.setText("0");

 

- 안드로이드 앱 내 xml 파일에서 'count_text'라는 Id를 가진 TextView를 찾고

- 해당 TextView에 "0"이라는 텍스트를 보이게 하는 코드

 

findViewById(R.id.count_text)에서의 R은 안드로이드 앱의 리소스(Resources)를 나타내는 클래스

R 클래스는 앱이 컴파일될 때 자동으로 생성되며, 리소스의 유형과 이름에 따라 여러 하위 클래스를 가짐

- R.layout는 레이아웃 리소스에 대한 상수를 포함하는 클래스

- R.id 레이아웃 내의 뷰에 할당된 고유한 ID 관리

 

    public void buttonCount(View view) {
        count++;
        if (countText != null) {
            countText.setText(Integer.toString(count));
        }
    }

 

아까 id 로 객체 지정한 countText를 바꾸어주는 함수 설정

해당 함수는 xml 파일에서 정의된 위젯들 중에, buttonCount라는 이벤트와 연결되어 있는 버튼이 눌렸을 때 동작함

 


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginStart="137dp"
        android:layout_marginTop="246dp"
        android:text="Hello World!" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginStart="62dp"
        android:layout_marginTop="66dp"
        android:text="Name" />

    <Button
        android:id="@+id/buttonCount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginStart="158dp"
        android:layout_marginTop="316dp"
        android:text="Count!"

        android:onClick="buttonCount"/>

    <Button
        android:id="@+id/buttonReset"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="291dp"
        android:text="Reset!"

        android:onClick="buttonReset"
        />

    <TextView
        android:id="@+id/count_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="210dp"
        android:text="TextView" />

</RelativeLayout>

 

728x90
728x90

1. 동적결합(Dynamic Binding)의 개념

프로그램이 실행 중일 , 어떤 함수나 메서드를 호출할 실제로 어떤 코드를 실행할지를 결정하는 것

- 즉, 함수 호출이 어떤 객체나 클래스의 실제 버전을 호출할지 런타임(runtime) 시점에 결정하는 

- 주로 객체 지향 프로그래밍에서 다형성을 구현하는 사용됨

 

1) '프로그램 실행 중'에 객체의 실제 타입을 고려

2) 해당 타입에 맞는 함수나 메서드를 호출

 

- 이를 통해 서로 다른 객체 동일한 함수 또는 메서드 호출하더라도, 객체의 고유한 동작 수행할 있음


2) c++에서 동적 결합을 구현하는 두 가지 주요 메커니즘

 

2-1. 가상함수 (virtual functions)

- 함수 앞에 virtual 키워드를 사용

- 가상 함수는 기본형 클래스에서 선언되고 파생 클래스(derived class)에서 재정의(override)할 수 있는 함수

- 가상 함수를 사용하면 런타임 시에 객체의 실제 타입에 따라 올바른 함수 버전이 호출됨

class Shape {
public:
    virtual void draw() {
        // 기본 구현 }
};

class Circle : public Shape {
public:
    void draw() override {}
};

2-2. 가상테이블 (virtual table)

- 가상 함수를 사용할 때, C++ 컴파일러는 객체에 대한 가상 함수 포인터 테이블을 생성함

- 테이블은 가상 함수의 주소를 저장하고, 실제 함수 호출 시에 테이블을 참조하여 올바른 함수를 호출함

 

void drawShape(Shape* shape) {
    shape->draw(); // 동적 결합
}

int main() {
    Circle circle;
    Square square;

    drawShape(&circle); // Circle 클래스의 draw()가 호출됨
    drawShape(&square); // Square 클래스의 draw()가 호출됨

    return 0;
}

구체적인 예제로 동적 결합 이해하기

 

기초형 클래스의 pointer으로 구성된 포인터 array를 선언

→ 해당 array에 기초형 클래스 Time뿐 아니라, 상속 클래스인 NewTime의 주소값도 저장됨

array의 각 원소에 대해 virtual 메서드인 show()를 실행시켜줌

(show 실행될 때마다, 어떤 class 타입인지 실시간으로 판단해스 해당 타입에 대응되는 virtual 메서드를 실행시킴)

 

time.h

#include<iostream>
using namespace std;

#ifndef FIRE_C_TIME_H
#define FIRE_C_TIME_H

class Time{
private:
    int hours;
    int mins;
public:
    Time();
    Time(int, int);

    /* virtual 통해 가상 메소드 선언 */
    virtual void show(); //가상메소드
    virtual ~Time(); //파괴자 역시 가상 메소드로 선언

    int getHour(){return hours;}
    int getMins(){return mins;}

    Time operator*(int n);
    friend Time operator*(int, Time&);
};

class NewTime : public Time {
private:
    int day;
public:
    NewTime(); //생성자
    NewTime(int, int, int); //생성
    void show();
};

#endif //FIRE_C_TIME_H

time_func.cpp

#include "time.h"

Time::Time(){
    hours = 0;
    mins = 0;}

Time::Time(int h, int m){
    hours = h;
    mins = m;}

void Time::show(){
    cout << hours << "시간 " << mins << "분" << endl;}

Time::~Time(){}

NewTime::NewTime() : Time(){
day = 0;
}

NewTime::NewTime(int h, int m, int d) : Time(h, m) {
day = d;
}

void NewTime::show(){
    cout << day << "일 " << getHour() << "시간 " << getMins() << "분" << endl;
}

main.cpp

#include "time.h"
#include "time_func.cpp"

const int MAX = 3;

int main(){
    Time* times[MAX]; //기초형 Time 클래스의 포인터들이 저장된 배열
    //이곳에 Time 기초형 클래스의 포인터도, NewTime 상속 클래스의 포인터도 담김
    int day;
    int hours;
    int mins;

    for (int i = 0; i < MAX; i++) {
        cout << i + 1 << "번째 원소를 정의합니다." << endl;
        cout << "시간을 입력하십시오." << endl;
        cin >> hours;
        cout << "분을 입력하십시오." << endl;
        cin >> mins;
        char check;
        cout << "일 정보가 있다면 1, 없다면 0을 입력하십시오." << endl;
        cin >> check;
        if (check == '0')
            times[i] = new Time(hours, mins);
        else {
            cout << "일을 입력하십시오." << endl;
            cin >> day;
            times[i] = new NewTime(hours, mins, day);
        }
    }

    for (int i = 0; i < MAX; i++){
        cout << i+1 << "번째 정보입니다." <<endl;
        times[i]->show();
        //show를 virtual로 선언했기 때문에,
        //times: time의 pointer 배열이지만
        //Times이면 Time의 show()가, NewTime이면 NewTime의 show()가 실행됨
    }

    for (int i = 0; i < MAX; i++){
        delete times[i]; //delete의 경우 time형에 대한 delete만 이루어짐
        //NewTime 객체의 경우 제대로 delete되지 않음
        //이를 위해 파괴자 역시 virtual로 선언해야 함

    }

    return 0;}
728x90
728x90

1. 기초 클래스에서 가상 메서드를 선언하면, 그 함수는 기초 클래스 및 파생되는 클래스에서 모두 가상이 됨

2. 객체에 대한 참조 or 포인터를 사용하여, 가상 메서드가 호출되면 → 참조나 포인터를 위해 정의된 메서드를 사용하지 않고 객체형을 위해 정의된 메서드를 사용한다. (=동적 결합)

3. 상속을 위해 기초 클래스로 사용할 클래스를 정의할 때, 파생 클래스에서 다시 정의해야 되는 클래스 메서드들은 가상 함수로 선언해야 한다.

 


기초 클래스의 데이터와 상속 클래스의 데이터를 출력하는 함수(메서드)를 만들고자 한다.

기존에는 각각에 서로 다른 메서드 show() / print() 를 정의했었다면,

이번에는 동일한 이름의 show() 메서드로 기초 클래스와 상속 클래스의 데이터를 출력해주고자 한다.

이를 위해서는 기초 클래스의 public 영역에서, virtual 키워드를 통해 show 메서드를 '가상 메서드'로 선언하여야 한다.

 

time.h

#include<iostream>
using namespace std;

#ifndef FIRE_C_TIME_H
#define FIRE_C_TIME_H

class Time{
private:
    int hours;
    int mins;
public:
    Time();
    Time(int, int);

    /* virtual 통해 가상 메소드 선언 */
    virtual void show();
    //가상 메소드: 프로그램에서 서로 독립된 메소드 정의가 있다는 것을 알려줌
    //show가 호출되었을 때, 호출한 객체를 따져서, 대응되는 함수를 선택함
    //현재 show가 가상 메소드로 정의된 상태

    int getHour(){return hours;}
    int getMins(){return mins;}
    ~Time();

    Time operator*(int n);
    friend Time operator*(int, Time&);
};

class NewTime : public Time {
private:
    int day;
public:
    NewTime(); //생성자
    NewTime(int, int, int); //생성
    void show();
};

#endif //FIRE_C_TIME_H

 

time_func.cpp

#include "time.h"

Time::Time(){
    hours = 0;
    mins = 0;}

Time::Time(int h, int m){
    hours = h;
    mins = m;}

// (1) 기초형 클래스에서 정의된 show() 메서드
void Time::show(){
    cout << hours << "시간 " << mins << "분" << endl;}

Time::~Time(){}

NewTime::NewTime() : Time(){
day = 0;
}

NewTime::NewTime(int h, int m, int d) : Time(h, m) {
day = d;
}

// (2) 상속 클래스에서 정의된 show() 메서드
/* show가 어디에서 호출되느냐에 따라 다른 기능 수행 - Time vs NewTime */

void NewTime::show(){
    //show(); 이름이 동일해서 재귀적으로 호출되는 문제 발생
    //기초형 클래스의 public 함수를 새로 생성 - private 멤버변수를 반환해주는.
    cout << day << "일 " << getHour() << "시간 " << getMins() << "분" << endl;
}

 

main.cpp

#include "time.h"
#include "time_func.cpp"

//public 함수를 다형으로 사용하기

int main(){
    Time temp1(1, 2);
    NewTime temp2(3, 30, 2);

    temp1.show();
    temp2.show();

    return 0;}

/*1시간 2분
2일 3시간 30분*/

 

728x90

'개발 > c++' 카테고리의 다른 글

[c++] 서로 다른 & (참조자/주소반환)  (0) 2023.09.24
[c++] 동적 결합  (0) 2023.09.11
[c++] 클래스 상속  (0) 2023.09.10
[c++] friend (feat. 연산자 오버로딩 응용)  (0) 2023.09.10
[c++] 연산자 오버로딩  (0) 2023.09.10
728x90

- 기초 클래스 (오리지널 원본)

 

- 파생 클래스

1. 파생 클래스형의 객체 안에는 기초 클래스형의 데이터 멤버들이 저장됨

2. 파생 클래스형의 객체는 기초 클래스형의 메서드를 사용할 수 있음

3. 단, 기초 클래스형의 private member에는 접근할 수 없음 → 멤버 초기자 리스트를 통해 접근할 수 있게 됨

4. 파생 클래스는 자기 자신의 생성자를 필요로함

5. 파생 클래스는 부가적인 데이터 멤버들과 멤버 함수를 임의로 추가할 수 있음

 

**아래 주석코드의 설명 잘 읽기,,

 

time.h

#include<iostream>
using namespace std;

#ifndef FIRE_C_TIME_H
#define FIRE_C_TIME_H

class Time{
private:
    int hours;
    int mins;
public:
    Time();
    Time(int, int);
    void show();
    ~Time();
};

/*클래스 상속*/
//파생 클래스: 오리지널 클래스인 Time을 상속받음
class NewTime : public Time {
private:
    int day;
public:
    NewTime(); //생성자
    NewTime(int, int, int); //생성자
    void print();

};

#endif //FIRE_C_TIME_H

time_func.cpp

#include "time.h"

Time::Time(){
    hours = 0;
    mins = 0;}

Time::Time(int h, int m){
    hours = h;
    mins = m;}

void Time::show(){
    cout << hours << "시간 " << mins << "분" << endl;}

Time::~Time(){}


// " : Time()" 부분은 '멤버 초기자 리스트'
// 기초형 클래스의 private member에 접근할 수 있게 됨
NewTime::NewTime() : Time(){
//Time()이 먼저 생성된 뒤 해당 내용이 NewTime에 전달되어, hours = mins = 0으로 초기화됨
//NewTime()에서는 day만 초기화해주면 됨
day = 0;
}

NewTime::NewTime(int h, int m, int d) : Time(h, m) {
//Time(h,m)이 생성된 뒤 NewTime의 h, m에 전달해줌
//d만 따로 정의해주면 됨
day = d;
}

void NewTime::print(){
    cout << day << "일 " << endl;
    show();
    // hours와 mins는 NewTime의 멤버변수가 아니므로 직접 접근하지는 못함
    // 따라서 기초형 클래스의 함수 통해 출력함
}

main.cpp

#include "time.h"
#include "time_func.cpp"

int main(){
    NewTime temp1();
    NewTime temp2(3, 30, 2);

    temp2.print();

    return 0;}

/*2일
3시간 30분*/
728x90

+ Recent posts