해당 포스팅에서 언급된 내용은 Ndroid 에서 제공합니다.

https://github.com/skaengus2012/Ndroid


안드로이드 개발을 진행하다보면 Activity 의 생명주기와 스레드 사용지점이 맞지 않아 누수가 되곤 합니다. 그러한 이유로 WeakReference 를 사용하란 이야기가 많이 나오곤 합니다.


보통 Activity 인스턴스를 약한참조 관계로 가지고 있습니다. 그리고 해당 인스턴스의 메소드를 사용하기 위해 우린 객체를 꺼내서 다음과 같이 사용합니다.


1
2
3
4
5
6
MyActivity activity = easyWeakReference.get();
        
if (activity != null) {
    // 메모리가 해제되어 더이상 존재하지 않는 객체인지 확인할 필요 존재!
    activity.func1();
}
cs


심플하게 사용할 수 있지만, 


프로그램의 덩치가 커지고 WeakReference 를 사용할 일이 많아진다면,


별 거 아닌 것 같은 저 null check 는 매우 귀찮고 중복작업일 수 있습니다.


이 문제는 아래의 WeakReference 의 상속체를 제작함으로 간단하게 해결할 수 있습니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
public class NxWeakReference<T> extends WeakReference<T> {
 
    /**
     * 단순한 상속에 대한 생성자 제작
     * @param referent
     */
    public NxWeakReference(T referent) {
        super(referent);
    }
 
    /**
     * 단순한 상속에 대한 생성자 제작
     * @param referent
     * @param q
     */
    public NxWeakReference(T referent, ReferenceQueue<super T> q) {
        super(referent, q);
    }
 
    /**
     * 약한 참조 속 실제 객체의 사용
     * @param weakReferenceConsumer
     */
    public void run(IWeakReferenceConsumer<T> weakReferenceConsumer) {
        T t = this.get();
 
        if (t != null) {
            weakReferenceConsumer.accept(t);
        }
    }
 
    /**
     * 약한 참조 속 실제 객체의 사용
     *
     * <pre>
     *     call back 의 개념 사용
     * </pre>
     *
     * @param weakReferenceFunction
     */
    public Object call(IWeakReferenceFunction<T> weakReferenceFunction) {
        Object result = null;
 
        T t = this.get();
 
        if (t != null) {
            result = weakReferenceFunction.accept(t);
        }
 
        return result;
    }
 
    /**
     * 약한 참조 속 실제 객체의 사용
     *
     * <pre>
     *      call back 개념 사용
     *      defaultValue 사용
     * </pre>
     *
     * @param weakReferenceFunction
     * @param defaultValue
     * @return
     */
    public Object call(IWeakReferenceFunction<T> weakReferenceFunction, Object defaultValue) {
        final Object result = call(weakReferenceFunction);
 
        if (result == null) {
            return defaultValue;
        } else {
            return result;
        }
    }
 
    /**
     * WeakReference 의 내부객체를 사용하기 위한 Consumer 인터페이스
     * @param <T>
     */
    @FunctionalInterface
    public interface IWeakReferenceConsumer<T> {
        void accept(T t);
    }
 
    /**
     * WeakReference 의 내부객체를 사용하기 위한 Function 인터페이스
     * @param <T>
     */
    @FunctionalInterface
    public interface IWeakReferenceFunction<T> {
        Object accept(T t);
    }
}
 
cs


상속 후 새로 제작된 accept 는 위의 null 체크를 수행하도록 하며, 실제 비지니스 로직은 함수형 인터페이스로 동작파라미터화 시켰습니다. 


동작 파라미터화가 무엇인지 궁금하다면, 이곳으로 이동!!



이제 비지니스 로직은 다음과 같이 단순화하여 개발할 수 있습니다.


1
easyWeakReference.run(MyActivity::func1);
cs

함수형 프로그래밍을 조금만 알면 쉽게 작업은 단순화시킬 수 있습니다. 




반응형
Posted by N'