• RxJava2
    • 보통 Retrofit과 함께 사용한다.
    • MVVM 패턴과는 직접적인 연관은 없고, 모든 디자인패턴에서 사용할 수 있는 느낌?
    • Java8 람다식을 사용해 코드를 더 간결하게 쓸 수 있지만... 지금 그거까지 건드리면 머리 터진다...
    • Observable과 Observer 두개의 관점으로 나뉜다.
    • Observable 객체에서 .method()를 사용하여 다양한 역할/설정이 가능하다.
    • 함수중에는 filter / create / transform 형식의 함수들이 존재한다.
    • LiveData와 얼추 역할이 비슷하다. 인줄 알았지만 아니다...
    • 사용하는 가장 큰 이유 : 코드간결 -> 유지보수 측면 Good
    • 아래의 링크를 통해 함수의 역할들을 배울 수 있다.
    • RxAndroid와 같이 사용하여 쓰레딩을 쉽게 한다.
    • LiveData와 다르게 Disposable이라는 객체를 사용하여 더이상 '구독'하지 않는 상황이거나 사용하지 않을 때는 LifeCycle를 건드려야한다. (LiveData는 직접 건드리지 않아도 알아서 됨)
  • RxAndroid
    • 쓰레딩을 쉽게해주는 역할을 한다.
      • subscribeOn() - Background
      • observeOn() - Main Thread

https://codingwithmitch.com/courses/rxjava-rxandroid-for-beginners/

  • Retrofit
    • 서버에 요청할 때 사용, OKHttp에 의존한다
    • 서버에서 받아온 Data를 Observable로 받을 수 있다.(Dependency를 추가해야함. implementation)
      • 즉 그 Observable은 RxJava2를 사용하여 Observe할 수 있으며 filter나 다양한 함수를 사용하여 Data를 조작할 수 있다.
    • MVVM패턴에서 interface로 선언을 한다.
  • DataBinding
    • MVVM 패턴에서 사용되는 기법
    • LiveData와 사용
    • MVC같은 패턴에서는 C에서 findbyviewId(?)로 객체를 생성하여 찾아서 textview.text="asd" 처럼 해줬지만 Reactive Programming을 함께 사용하여 일일히 그렇게 할 수 없기에 사용한다.
    • gradle:App 단위에서 databinding을 enable해줘야한다.
    • 사용할 layout을 <layout>으로 감싸고 그 안에 <data>로 변수를 사용할 수 있다.
      • 주로 ViewModel을 가져와 ViewModel내의 변수의 값을 스스로 받아와 설정(수정)한다.
    • View(Activity / Fragment)에서는 Databinding을 위해 코드를 써줘야한다.
      • MVC 패턴에서의 setcontentview() 대신에 
 val binding = DataBindingUtil
                .setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        binding.lifecycleOwner = this // LiveData를 사용하기 위해서 없으면 Observe할때마다 refresh안딤

        //binding 객체는 layout의 객체로 생각한다?

        //ViewModelProviders를 사용하여 ViewModel을 불러온다.
        val viewModel = ViewModelProviders.of(this)[MainViewModel::class.java]
        binding.viewModel = viewModel//layout의 binding 객체의 name = viewModel 에 viewModel을 초기화
  • MVVM 패턴
    • 디자인 패턴 중 하나로 MVC / MVP / MVVM / MVI(?) 이건 처음들어봄
    • 작은 프로젝트에서는 File이 많아진다는 단점이 존재하지만 큰 프로젝트에서는 Activity하나당 View하나인 1:1 대응 관계를 벗어나 ViewModel하나에 여러개의 View가 붙을 수 있다.
    • 사용하는 가장 큰 이유는 역시 가독성
  • LiveData
    • 살아있는 Data?
    • DataBinding을 할 수 있는 객체
    • 변경이 되는 것을 알아 차릴 수 있다.
    • RxJava와는 다른 느낌
    • RxJava와 달리 스스로 Dispose()를 해준다(생명주기에 따라서)
  • 뇌로 하는 상상
    • 사용할 view(layout)을 <layout>으로 감싼 뒤 <data>로 Data를 받아올 ViewModel을 변수로 생성 및 작업 
    • View와 ViewModel을 연결한다.(View에서 ViewModel을 생성한다. ViewModelProviders를 사용)
    • View에서 sercontentview() 대신 binding 작업을 한다.
    • ViewModel에서 Observable<LiveData<T>>을 생성한다.
    • Retrofit(Interface)에서 HTTP 통신 Method(?)를 만들고 반환 자료형은 Observable,Flowable
    •  Retrofit(Class)에서 전에 만든 Method를 구현한다.
    • ViewModel에서 Retrofit(Class)를 객체로 생성하여 원할 때 API를 호출하여 결과값(Observable)반환
    • ViewModel에서 Observer를 만든다.(.subscribe(......)를 사용하여)
    • Observer(subscribe()함수에서 LiveData를 받아온 Data로 바꿔준다.(받아온 Data는 Retrofit을 사용해 호출한 API의 반환값)
    • onNext()를 통해 LiveData<T>가 변경되면 DataBinding을 했기 때문에 View에서 자동으로 변경됨

 

 

 

 

1. Reactive Programming이란?

- Observable한 Object : 다른 객체로부터 Observed 되는 객체

- 속성이 변경되면 Observer에게 알림 (LiveData와 MVVM 패턴과 같다)

 

+ RxJava / RxAndroid vs LiveData / MVVM

 Rx의 기능 중 다수(모두가 아님)를 LiveData와 MVVM 패턴으로 사용 가능하지만 Rx만의 이점이 존재

 

이점 1. Operator - Observable한 Object를 Simple하게 만든다.

       2. Threading - Thread간에 Data를 쉽게 주고받을 수 있다.(Background에서 작업실행 / Main에서 결과 검색)

(이전 포스팅에서 적었던 것 처럼 LiveData를 사용하면 Dispose를 안해도 된다. Dispose에 대해서는 후에 포스팅할 것이다.)

 

 

2. RxJava vs RxAndroid

- RxAndroid는 Android에서 RxJava를 보다 쉽게 쓰게 하는 Component를 갖는다.(Scheduler는 Threading을 쉽게 한다)

- 모든 비동기 작업을 Observable<T>로 해결한다.

 

 

 

 

 

 

 

 

 

이전 포스팅에서 MVVM을 사용하기 위해 LiveData와 코루틴을 사용한 프로젝트를 간략히 적고 내가 느낀 점을 적었다.

 

더 알아보다 보니 Rxjava를 사용해야지만 MVVM의 완성이라는 사람들도 존재하는 것 같아 공부하고 내 생각을 적어본다.

 

기본적으로 Reactive Extension 이라는 개념에서 나왔다고 한다.

많은 Event로 하여금 좀더 유연하게/유동적으로 변경된다는 말로 이해했다.

 

기본적으로 끊임없이 변하는 Data의 흐름을 알기 위해 사용한다.

 

두 가지의 역할? 이 존재한다

  • Observable : Data의 Stream을 생성한다. Data를 발행한다.
  • Subscriber : Data Stream에서 Data를 건져 사용한다. 사용을 안할 때는 사용해제를 해줘야 함.(사용 해제는 unsubscribe(), dispose() -> dispose는 완전히 사용하지 않게 될 때)

Observable - onNext() , onCompleted() , onError() 의 3가지 메소드가 존재하며 

 

각각 onNext() - 새로운 Data를 구독하고 있는 Subscriber에게 전달

onCompleted() - Stream을 종료

onError() - 에러 발생시

 

계속해서 변하는 Data를 API를 통해 들어오는 Data라고 가정해보자.

어떠한 API를 통해 Data가 지속적으로  변화되어 들어올 때 onNext()를 통해 그 바뀐 Data를 뿌려 Subscriber가 변화된 Data를 알게 하는 것이다.

(이때, Data들을 filter, map 와 같은 operator를 통해 거르고 계산하여 반환하고 할 수 있다.)

 


RxAndroid - Rxjava를 사용하기 위해 Android의 Rxjava? 같은 느낌이다.

 

가장 큰 역할은 스케줄러는 제공하는 것이다.

 

뒤의 코드에서 더 설명하겠다.

 


예제로 

 

온도를 받아오는 API를 사용하여 그 온도를 Rxjava와 RxAndroid를 사용해 화면에 뿌리는 App을 만들어보자.

 

API를 사용하는 것 대신 새로운 쓰레드를 생성하여 그 쓰레드가 온도를 뿌려주는 방법으로 진행하겠다.

 

MainActivity

class MainActivity : AppCompatActivity() {
val TAG = "RxAndroid.MainActivity"
    val manager = TemperatureManager()
    var disposable : Disposable?=null
    var github = GithubClient()
    lateinit var binding : ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil
            .setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        binding.currentTemperatureView.text = "받아온 온도가 없습니다."

        val executorService = Executors.newSingleThreadScheduledExecutor()
        executorService.scheduleAtFixedRate({
            val nextTemperature = Random().nextInt(15)+10
            manager.setTemperature(TemperatureManager.Temperature(nextTemperature))
        }, 0L,3, TimeUnit.SECONDS)


        disposable = manager.updateEvent().subscribe(this::updateView)
        //subscribe하는 Item들을 updateView에서 처리하도록 하겠다 - java8식





    }

    override fun onDestroy() {
        super.onDestroy()
        disposable?.dispose()
    }

    fun updateView(temperature: TemperatureManager.Temperature)
    {
        binding.currentTemperatureView.text = "현재온도 : ${temperature.currentTemperature}"
    }


}

TemperatureManager

 

class TemperatureManager
{
    class Temperature(degree : Int)
    {
        var currentTemperature =degree


    }

    var subject : PublishSubject<Temperature> = PublishSubject.create()
    //PublishSubject가 생성하는 subject는 Observable을 UI Event와 연결지어서 사용하고 싶을 때
    //유저가 화면을 언제 터치할지 모를 때 -> 이럴 때 subject를 사용
    //사용 하는 녀석
    // 차이점 : Observable은 내부에서 Data를 emit하지만 subject는 코드처럼 외부에서 Data를 주입가능
    // 아래의 함수 setTemperature()에서 onNext로 데이터를 전달하는 부분을 주목

    fun setTemperature(temperature : Temperature)
    {
        subject.onNext(temperature)
    }

    //updateEvent에서 subscribeOn과 observeOn은 subscribe와 observe를 전담할 쓰레드를 지정
    //UI Update는 메인쓰레드에서 실행해야하므로 AndroidSchedulers.mainThread()를 지정
    fun updateEvent() : Observable<Temperature>
    {
        return subject.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
    }

}

 


코드를 좀더 자세히 알아보자

 

 binding = DataBindingUtil
            .setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        binding.currentTemperatureView.text = "받아온 온도가 없습니다."

binding을 사용하여 layout을 관리한다.

 

 val executorService = Executors.newSingleThreadScheduledExecutor()
        executorService.scheduleAtFixedRate({
            val nextTemperature = Random().nextInt(15)+10
            manager.setTemperature(TemperatureManager.Temperature(nextTemperature))
        }, 0L,3, TimeUnit.SECONDS)

3초마다 새로운 온도를 생성하는 쓰레드를 생성한다.(API를 대신하는 역할)

 

 disposable = manager.updateEvent().subscribe(this::updateView)
        //subscribe하는 Item들을 updateView에서 처리하도록 하겠다 - java8식

 

TemperatureManager에는 주석으로 적어놨다.

 

 

+ Recent posts