Android observe함수로 이해하는 제네릭 표현!

98oys·2022년 7월 2일
0

language

목록 보기
2/9

Android Studio(androidx.lifecycle.Observer)에는 LiveData를 observe하는 함수가 있습니다.

라이브러리 내부 설명입니다!😊

Adds the given observer to the observers list within the lifespan of the given owner. The events are dispatched on the main thread. If LiveData already has data set, it will be delivered to the observer.
The observer will only receive events if the owner is in Lifecycle.State.STARTED or Lifecycle.State.RESUMED state (active).
If the owner moves to the Lifecycle.State.DESTROYED state, the observer will automatically be removed.
When data changes while the owner is not active, it will not receive any updates. If it becomes active again, it will receive the last available data automatically.
LiveData keeps a strong reference to the observer and the owner as long as the given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to the observer & the owner.
If the given owner is already in Lifecycle.State.DESTROYED state, LiveData ignores the call.
If the given owner, observer tuple is already in the list, the call is ignored. If the observer is already in the list with another owner, LiveData throws an IllegalArgumentException.
Params:
owner – The LifecycleOwner which controls the observer
observer – The observer that will receive the events

간단하게 번역을하면 아래와 같습니다.😂

지정된 소유자의 수명(lifespan) 내에 지정된 관찰자를 관찰자 목록에 추가합니다.
이벤트는 기본 스레드에서 보내게(dispatch)됩니다.
만약 소유자가 Lifecycle.State.STARTED 또는 Lifecycle.State.RESUMED 상태일 때, 관찰자(observer)는 오직 이벤트만 받습니다.
만약 소유자가 Lifecycle.State.DESTROYED state로 이동하는 경우, 관찰자는 자동적으로 제거됩니다.
소유자가 not active이고 데이터가 변경될 때, 아무런 업데이트도 받지 않습니다.
만약 다시 active가 된다면, 마지막으로 사용 가능한 데이터는 자동으로 수신됩니다.
LiveData는 주어진 LifecycleOwner가 파괴되지 않는 한 관찰자(Observer)와 소유자(Owner)에 대한 강력한 참조(string reference)를 유지합니다.
삭제(destroyed)된다면, LiveData는 관찰자와 소유자의 참조를 제거합니다.
만약 이미 주어진 소유자가 Lifecycle.State.DESTROYED 상태라면, LiveData는 호출(call)을 무시합니다.
만약 주어진 소유자가, 리스트안에 관찰자 튜플이 이미 있다면, 호출은 무시됩니다.
만약 관찰자가 이미 다른 소유자와 함께 리스트에 있는 경우 LiveData는 예외 IllegalArgumentException를 던집니다.
파라미터 :
owner - 관찰자를 컨트롤하는 라이플사이클오너
observer - 이벤트를 받는 옵저버

😶‍🌫️ 옵저버의 동작 방식

  1. 이벤트를 기본 스레드에 전달
  2. STARTED ~ RESUMED 상태일 때만 이벤트를 받음
  3. DESTROYED 상태가 된다면 관찰자와 소유자 참조 제거
  4. 비활성화(not active) 상태라면 아무른 작업 하지 않음
  5. 비활성화 -> 활성화가 된다면 사용가능한 데이터 자동으로 수신
  6. LiveData는 LifecyclerOwner가 파괴되지 않는 한 관찰자와 소유자에 대한 강한 참조를 유지
  7. 목록안에 관찰자 튜플이 존재한다면 호출 무시하고 예외를 던집니다.

위와 같은 방식으로 동작 합니다!

observe() 함수는 주로 MVVM 패턴에서 ViewModel의 Data 변화를 관찰할 때 사용합니다.

observe() 함수

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }

함수의 인자를 자세히보면 <? super T>라는 코드가 있습니다.

<? super T>(와일드카드)는 제네릭의 종류 중 하나입니다.

와일드카드(wild card)란 이름에 제한을 두지 않음을 표현하는 데 사용되는 기호입니다.
자바의 제네릭에서는 물음표 기호를 사용하여 이러한 와일드카드를 사용할 수 있습니다.

😧와일드카드 사용

 <?> // 타입 변수에 모든 타입을 사용할 수 있다.
 <? extends T> // T 타입과 T 타입을 상속받는 자손 클래스 타입만을 사용할 수 있다.
 <? super T> // T타입과 T타입이 상속받은 조상 클래스 타입만들 사용할 수 있다. 
  • 상속관계에서 존재하는 클래스만 자료형으로 받고 싶을 때,
  • T: 자식클래스로 고정으로 지정해주고 자식클래스와 연관이 있는 부모클래스는 전부 적용된다.(매개변수로 허용)

😁예시


public class Main<T>{
    public void main(String[] args) {

	    public void printSuperData(Observe<? super T> observe) {
	  			...
    	}
	}
}

interface Observe<T> {
    void changed(T t);
}

위와 같이 작성하면 Andoid의 LiveData Observe 함수를 구현할 수 있습니다.

제네릭에 대해서 조금 더 공부해보겠습니다!

class A {
    String returnString() {
        return "나는 A";
    }
}

class B extends A {
    List<B> list = new ArrayList<B>();

    String returnString() {
        return "나는 B";
    }
}

class C extends B {
    String returnString() {
        return "나는 C";
    }
}

Class A를 상속받는 Class B, Class B를 상속받는 Class C가 있을 때,

public abstract class WildCard<T> {
    public static void main(String[] args) {
        // List는 인터페이스이기 때문에 ArrayList 생성 후 Upcasting 이용
        List<String> list = new ArrayList<>();
        list.add("t1");
        list.add("t2");
        printData(list);

/**
         * up casting, down casting 예제
         * <p>
         * upcasting이란 서브타입의 인스턴스를 수퍼타입의 변수로 전근하는 것을 말합니다.
         * 즉, 자식 클래스가 부모 클래스 타입으로 캐스팅 되는 것을 뜻합니다.
         * 이때 서브 타입에서는 수퍼타입에 선언된 필드 혹은 메서드만 접근 가능합니다.
         * https://viera.tistory.com/3
         * 수퍼타입클래스 : 부모클래스를 상속
         * 서브타입클래스 : 부모로부터 상속받은 하위 클래스
         */

        B b = new B();  // B 객체 생성
        System.out.println(b.returnString());  // 객체 확인 : "나는 B"
        System.out.println(b.getClass().getSimpleName());

        A a = b;    // b를 A타입으로 upcasting (자동형변환)
        System.out.println(a.returnString());
        System.out.println(a.getClass().getSimpleName());

        A a2;

        B b2 = (B) a;   // upcasting한 a를 b로 downcasting
        System.out.println(b2.returnString()); // down casting은 명시적변환 해야함
        System.out.println(b2.getClass().getSimpleName());
	}

list의 타입을 받아서 T에 담아 출력하는 함수입니다.

  • 모든 데이터 허용
	// 타입을 출력하는 함수
	public static void printData(List<?> list) {
        for (Object v : list) {
            System.out.println(v.getClass().getSimpleName());
        }
  • B클래스와 그 하위 클래스로 생성된 인스턴스만 허용
        public static void printExtendData (List < ? extends B > list){
            for (Object v : list) {
               System.out.println("printExtendData : " + v.getClass().getSimpleName());
    }
  • B와 부모인 A의 데이터만 허용
        public void printSuperData (Observe < ? super T > observe){
            for (Object v : list) {
               System.out.println("printExtendData : " + v.getClass().getSimpleName());
        }

참고 자료 :
제네릭 : http://www.tcpschool.com/java/java_generic_various

profile
Android Developer, Department of Information and Communication Engineering, Inha University

0개의 댓글