관리 메뉴

막내의 막무가내 프로그래밍 & 일상

[안드로이드] otto 라이브러리 ( An event bus by Square ) 본문

안드로이드/자바 & Previous

[안드로이드] otto 라이브러리 ( An event bus by Square )

막무가내막내 2019. 6. 16. 18:16
728x90

 

square사에서 만든 otto(오투) 라이브러리에 대해 포스팅을 해보겠습니다.

https://github.com/square/otto

 

square/otto

An enhanced Guava-based event bus with emphasis on Android support. - square/otto

github.com

참고 : https://gun0912.tistory.com/4

 

[안드로이드/Android]유용한 라이브러리 - Otto(Event Bus)

Otto라이브러리는 Square에서 만든 event bus형태의 라이브러리 입니다. 홈페이지 GitHub 예를들어보겠습니다. 3개의 Activity A,B,C가 있습니다. 이 3개의 화면은 모두 같은 데이터를 가지고 다른형태로 화면에..

gun0912.tistory.com

 

이 라이브러리는 bundle과 intent putExtra와도 조금 비슷하다고 처음에는 느꼈으나 이것을 더 강화시킨 라이브러리 같다는 생각이 들었습니다. 그리고 다른 액티비티에 있는 값들을 static으로 선언한것처럼 다른 액티비티의 원하는 값을 갖고 오는 듯한 효과를 가질 수 있습니다.

 

오토는 이벤트버스라고도 불립니다. 이벤트 버스라는 이름처럼 하는역할이 마치 버스와 비슷합니다.  제가 이해한대로 쉽게 설명하자면, 버스에 다른 액티비티 또는 프래그먼트에 전달할 데이터를 넣습니다. 그리고 버스는 이 데이터를 싣고 정류장마다(액티비티) 멈춥니다. 여기서 정류장은 액티비티마다 하나씩 존재할 수 있는데 액티비티에서 정류장을 설치해놀수도 있고 안해놓을 수도 있습니다. 즉 정류장을 설치해논 액티비티에만 데이터를 싣은 버스가 도착해서 그들이 원하는 데이터가 있으면 주게됩니다.

 

쉽게 설명하면 위와 같고 조금 더 정확히(?) 설명하면 이벤트를 감지하고자하는 액티비티 혹은 프래그먼트가 있고 이벤트가 발생하면 이벤트버스는 이벤트를 감지하는 액티비티 혹은 프래그먼트들에게 이벤트를 전달해줍니다. 그럼 받는쪽은 자신이 감지하고 있던 이벤트가 맞으면 데이터를 가져올 수 있습니다... 다른 분의 블로그나 공식문서 참고하시는게 정확하게 이해하는데는 더좋을 것 같습니다. ㅎㅎㅎ

 

저같은 경우는 어댑터에서 액티비티쪽으로 데이터를 전달하는 경우만 써보았습니다. 

 

이제 사용법에 대해 정리해보겠습니다. (제가 사용한 예제에서 가져오겠습니다.)

 

1. gradle에 다음을 추가합니다. 

implementation 'com.squareup:otto:1.3.8'

 

 

 

2. 먼저 가장중요한 버스 클래스부터 만들어보겠습니다. 다음과 같이 싱글톤 형식으로 생성합니다. BusProvider라는 이름으로 만들었습니다.

import com.squareup.otto.Bus;
import com.squareup.otto.ThreadEnforcer;

public class BusProvider {
    public static final Bus bus = new Bus(ThreadEnforcer.ANY);

    public static Bus getInstance(){
        return bus;
    }

    public BusProvider() {

    }
}

 

 

 

3. 처음 말할때 이벤트버스라고 했습니다. 이벤트 즉 데이터를 버스에 싣고 버스가 정류장을 한바퀴 도는것입니다.

그렇다면 제가 전달할 객체를 다음과 같이 정의해보록 하겠습니다. 객체도 전달 할 수 있으므로 전 객체로 정의해봤습니다.

public class HeartEvent {
    String id;
    boolean like;

    public HeartEvent(String id, boolean like) {
        this.id = id;
        this.like = like;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public boolean isLike() {
        return like;
    }

    public void setLike(boolean like) {
        this.like = like;
    }
}

 

 

 

 

 

4. 버스에 데이터를 넣어줍니다. 앞서 선언해논 HearEvent객체에 데이터를 저장해 버스에 실고 버스를 출발시켜보겠습니다.(이벤트버스 출발) BusProvider.getInstance().post(데이터); 이런식으로 해줍니다. 코드는 다음과 같습니다. 

heartBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    MiniGram miniGram = miniGramArrayList.get(getAdapterPosition());
                    if(miniGram.getLike()){
                        miniGram.setLike(false);
                        HeartEvent heartEvent = new HeartEvent(miniGram.getId(), false);
                        BusProvider.getInstance().post(heartEvent);
                    }else{
                        miniGram.setLike(true);
                        HeartEvent heartEvent = new HeartEvent(miniGram.getId(), true);
                        BusProvider.getInstance().post(heartEvent);
                    }
                }
            });

 

 

 

 

4. 이제 이 버스가 자기가 정류장을 설치한 액티비티 혹은 프래그먼트에 도착할 수 있도록 3번과 다른 액티비티에 정류장을 설치해보겠습니다.

4-1) 전역 변수로 Bus bus = BusProvider.getInstance(); 를 생성해줍니다.

4-2) onCreate() 안의 setContentView밑에 bus.register(this); 로 정류장을 등록해줍니다.

4-3) @Subscribe 어노테이션을 적어주고 이벤트버스에서 보낸 이벤트를 받을 수 있게 해줍니다. 저는 내부에 레트로핏통신을 하는 코드가 적혀있는데 그냥 매개변수로 HeartEvent에 보내준 데이터를 가져올 수 있다고 생각하시면 될 것 같습니다. 즉 이벤트가 발생한 뒤 정류장에 해당 이벤트가 도착하면 수행할 함수입니다.

 @Subscribe //이벤트버스에서 보낸 이벤트가 여기에 정착을 하는 정류소를 만든다고 생각
    public void updateLike(HeartEvent heartEvent) {//public항상 붙여줘야함
        miniGramService.updateLike(heartEvent.getId(), heartEvent.isLike()).enqueue(new Callback<MiniGram>() {
            @Override
            public void onResponse(Call<MiniGram> call, Response<MiniGram> response) {
                if(response.isSuccessful()){
                    Log.d("like update", "sucess");
                }else{
                    Log.d("like update", "failed");
                }
            }

            @Override
            public void onFailure(Call<MiniGram> call, Throwable t) {
                Log.d("like update", "not connected");
            }
        });
    }

 

 

 

 

5. 마지막으로 이 액티비티가 생명주기가 끝나거나 필요없는 시점에는 이벤트버스가 쓸데없이 해당 액티비티 정류장에 들어올 필요가 없습니다. 그러므로 등록한 정류장을 해제해주도록 합니다. 저는 finish()에 오버라이딩하여 구현을 했으나 해제시점은 원하는데에 하시면 됩니다. onDestory()에 해도 됩니다.

 @Override
    public void finish() {
        super.finish();
        bus.unregister(this); //이액티비티 떠나면 정류소 해제해줌
    }

 

 

 

이벤트를 감지하는(정류소등록을한) 액티비티 전체코드와 함께 이상 포스팅을 마치겠습니다. 감사합니다

package com.mtjinse.myminiinstgram;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;

import com.mtjinse.myminiinstgram.models.MiniGram;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;

import java.util.ArrayList;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity {
    public static final String BASE_URL = "http://memolease.ipdisk.co.kr:1337";
    Retrofit retrofit;
    MiniGramService miniGramService;

    RecyclerView minigram_recycler;
    MiniGramAdapter miniGramAdapter;
    LinearLayoutManager linearLayoutManager;
    ArrayList<MiniGram> miniGramArrayList = new ArrayList<>();

    Bus bus = BusProvider.getInstance();

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

        bus.register(this); //정류소 등록

        minigram_recycler = findViewById(R.id.minigram_recycler);

        //Retrofit 객체생성
        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    /*addConverterFactory(GsonConverterFactory.create())은
    Json을 우리가 원하는 형태로 만들어주는 Gson라이브러리 Retrofit2에 연결하는 것입니다 */

        miniGramService = retrofit.create(MiniGramService.class);
        miniGramAdapter = new MiniGramAdapter(MainActivity.this,miniGramArrayList);
        linearLayoutManager = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false);

        minigram_recycler.setLayoutManager(linearLayoutManager);
        minigram_recycler.setAdapter(miniGramAdapter);

        miniGramService.getMiniGram().enqueue(new Callback<List<MiniGram>>() {
            @Override
            public void onResponse(Call<List<MiniGram>> call, Response<List<MiniGram>> response) {
                if(response.isSuccessful()) {
                    List<MiniGram> getMiniGrams = response.body();
                    for (MiniGram miniGram : getMiniGrams){
                        miniGramArrayList.add(miniGram);
                    }
                    miniGramAdapter.notifyDataSetChanged();
                }else {
                    Log.d("MainiActivity", "failed");
                }
            }

            @Override
            public void onFailure(Call<List<MiniGram>> call, Throwable t) {

            }
        });
    }


    @Override
    public void finish() {
        super.finish();
        bus.unregister(this); //이액티비티 떠나면 정류소 해제해줌
    }

    @Subscribe //이벤트버스에서 보낸 이벤트가 여기에 정착을 하는 정류소를 만든다고 생각
    public void updateLike(HeartEvent heartEvent) {//public항상 붙여줘야함
        miniGramService.updateLike(heartEvent.getId(), heartEvent.isLike()).enqueue(new Callback<MiniGram>() {
            @Override
            public void onResponse(Call<MiniGram> call, Response<MiniGram> response) {
                if(response.isSuccessful()){
                    Log.d("like update", "sucess");
                }else{
                    Log.d("like update", "failed");
                }
            }

            @Override
            public void onFailure(Call<MiniGram> call, Throwable t) {
                Log.d("like update", "not connected");
            }
        });
    }
}

 

 

 

 

+) TIP

매번 정류장을 등록하고 해제하는게 번거롭고 귀찮을 수 있습니다.

그런 경우 이와같이 액티비티를 하나만들고 이 BaseActivity를 otto를 사용하는 액티비티에서 AppCompactActivity대신 extends해주면 알아서 정류장이 등록 해제됩니다.

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.squareup.otto.Bus;

public class BaseActivity extends AppCompatActivity {
    Bus bus = BusProvider.getInstance();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bus.register(this);
    }

    @Override
    public void finish() {
        super.finish();
        bus.unregister(this);
    }
}
728x90
Comments