본문 바로가기
코딩일기/날씨앱 만들기 프로젝트

날씨 앱 만들기 : Retrofit을 사용하여 날씨 API 호출하기 2(Java / MVVM)

by 욱파이어니어 2021. 9. 1.
728x90
반응형

저번 글에서는 

 

아래 순서중 3번까지만 진행을 했으니 이번 글에서는 4번부터 시작을 해서 마무리를 지어보려고 한다.

 

1. dependencies 추가 및 인터넷 권한 추가.

2. interface 생성

3. DTO 생성

4. Retrofit 객체 생성

5. 4번에서 생성한 객체를 통해서 http 통신하기

 

일단은 4번과 5번의 설명에 앞서 api 호출하는 OpenWeatherRepos class 의 전체 소스를 보여주겠다.

 

public class OpenWeatherRepos {
    //이 클래스에서는 API 통신을 통해서 데이터를 가져와야 한다.
    private final String TAG = "OpenWeatherRepository";
    private final static String BASE_URL = "https://api.openweathermap.org/data/2.5/"; //api의 baseURL을 상수로 적어서 올려놨다.
    private static OpenWeatherRepos instance;
    private Retrofit retrofit;
    private OpenWeatherAPI opwAPI;
    private OpenWeather opw;

    //OpenWeatherRepos 인스턴스 반환
    public static OpenWeatherRepos getInStance() {
        if(instance == null){
            instance = new OpenWeatherRepos();
        }
        return instance;
    }

    //날씨 정보를 직접적으러 받아와야 하는 부분
    public MutableLiveData<OpenWeather> getWeather() {

        //Retrofit 객체 생성 생성
        retrofit = new RetrofitService().getRetroInstance(BASE_URL);

        //인터페이스 객체 생성
        opwAPI = retrofit.create(OpenWeatherAPI.class);

        //API와 통신을 하는 함수 호출
        opw = new OpenWeather();
        MutableLiveData<OpenWeather> data = new MutableLiveData<OpenWeather>();
        callWeatherAPI(data);
        return data;
    }

    private void callWeatherAPI(MutableLiveData<OpenWeather> data) {

        //응답을 받아오는 부분
        Call<OpenWeather> call = opwAPI.getWeather("seoul","api키","kr");

        call.enqueue(new Callback<OpenWeather>() {
            //아래 함수들은 callback 함수들로써 연결이 완료되면 호출이 되는 부분이다.
            @Override
            public void onResponse(Call<OpenWeather> call, Response<OpenWeather> response) {
                data.postValue(response.body());
                Log.i(TAG,"API CONNECT SUCCESS");
            }

            @Override
            public void onFailure(Call<OpenWeather> call, Throwable t) {
                Log.d(TAG,"onFailure : "+t.getMessage());
            }
        });
    }

}

 

4. Retrofit 객체 생성

나는 Retrofit의 객체를 getWeather()에서 만들었다.

 

      //Retrofit 객체 생성 생성
        retrofit = new RetrofitService().getRetroInstance(BASE_URL);

        //인터페이스 객체 생성
        opwAPI = retrofit.create(OpenWeatherAPI.class);

위 과정을 통해서 Retrofit 객체를 생성했고

해당 Retrofit을 가지고 2번 과정에서 만든 interface의 객체를 생성했다.

 

그럼 이제 우리가 만든 interface의 객체를 사용해서 통신을 해보자.

 

 

5. 4번에서 생성한 객체를 통해서 http 통신하기

일단 호출하고 응답을 받아올 call변수를 생성해줬다.

 

        //응답을 하고 받아오는 부분
        Call<OpenWeather> call = opwAPI.getWeather("seoul","api키","kr");

그리고 생성한 call변수를 통해서 

백그라운드에서 api를 호출한다.

 

        call.enqueue(new Callback<OpenWeather>() {
            //아래 함수들은 callback 함수들로써 연결이 완료되면 호출이 되는 부분이다.
            @Override
            public void onResponse(Call<OpenWeather> call, Response<OpenWeather> response) {
                data.postValue(response.body());
                Log.i(TAG,"API CONNECT SUCCESS");
            }

            @Override
            public void onFailure(Call<OpenWeather> call, Throwable t) {
                Log.d(TAG,"onFailure : "+t.getMessage());
            }
        });

 

이렇게 소스를 작성하면 api의 통신이 성공적으로 되었다면 onResponse를 호출하게 되고

그게 아니라면 onFailure를 호출하게 된다.

 

 


 

 

그럼 이제 API의 통신은 완료 됐으니 MVVM 디자인패턴으로 어떻게 작동이 되는지 알아보자.

 

 

전체적인 흐름은 아래와 같다.

 

1. MainActivity(View)에서 MainActivityViewModel(ViewModel)의 API 호출하는

init() 메소드를 호출

 

public class MainActivity extends AppCompatActivity {

    private MainActivityViewModel mavm;
    private final String TAG = "MainActivity";
    private OpenWeather opw;

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

        mavm = new ViewModelProvider(this).get(MainActivityViewModel.class); //ViewModel의 값을 받아온다.
        mavm.init(); //ViewModel의 API 호출 메소드를 호출
        
        //여기서 바뀐 값들이 뭐가 있는지 확인하는 부분
        //ViewModel로부터 값을 LiveData를 가져온후 해당 값에 변경사항이 있을때 아래 함수를 호출하게 된다.
        mavm.getWeather().observe(this, new Observer<OpenWeather>() {
            @Override
            public void onChanged(OpenWeather openWeather) {
                Log.i(TAG,"API Connection finish");
                opw = mavm.getWeather().getValue();
                Log.i(TAG,opw.toString());
            }
        });
    }
}

 

2. MainActivityViewModel(ViewModel) 에서 OpenWeatherRepos(Model)의

API 호출 메소드 getWeahter()를 호출

 

public class MainActivityViewModel extends ViewModel {

    private final String TAG = "MainActivityViewModel";

    //이 클래스에서는 Model과 통신하여서 날씨 정보를 받아온다.
    private MutableLiveData<OpenWeather> weather;
    private OpenWeatherRepos opwRepo;

    public void init(){
        if(weather != null){
            return;
        }
        opwRepo = OpenWeatherRepos.getInStance(); //OpenWeatherRepos를 통해 객체 받아온다 
        weather = opwRepo.getWeather(); // 위에서 받아온 객체로 API 호출 메소드 호출
        Log.i(TAG,"API Connection finish");
    }

    public LiveData<OpenWeather> getWeather(){
        return weather;
    }
}

 

 

3. Model에서 API 호출

 

public class OpenWeatherRepos {
    //이 클래스에서는 API 통신을 통해서 데이터를 가져와야 한다.
    private final String TAG = "OpenWeatherRepository";
    private final static String BASE_URL = "https://api.openweathermap.org/data/2.5/"; //api의 baseURL을 상수로 적어서 올려놨다.
    private static OpenWeatherRepos instance;
    private Retrofit retrofit;
    private OpenWeatherAPI opwAPI;
    private OpenWeather opw;

    //OpenWeatherRepos 인스턴스 반환
    public static OpenWeatherRepos getInStance() {
        if(instance == null){
            instance = new OpenWeatherRepos();
        }
        return instance;
    }

    //날씨 정보를 직접적으러 받아와야 하는 부분
    public MutableLiveData<OpenWeather> getWeather() {

        //Retrofit 객체 생성 생성
        retrofit = new RetrofitService().getRetroInstance(BASE_URL);

        //인터페이스 객체 생성
        opwAPI = retrofit.create(OpenWeatherAPI.class);

        //API와 통신을 하는 함수 호출
        opw = new OpenWeather();
        MutableLiveData<OpenWeather> data = new MutableLiveData<OpenWeather>();
        callWeatherAPI(data);
        return data;
    }

    private void callWeatherAPI(MutableLiveData<OpenWeather> data) {

        //응답을 하고 받아오는 부분
        Call<OpenWeather> call = opwAPI.getWeather("seoul","d0a0f80f34551266ab6f092780304575","kr");

        call.enqueue(new Callback<OpenWeather>() {
            //아래 함수들은 callback 함수들로써 연결이 완료되면 호출이 되는 부분이다.
            @Override
            public void onResponse(Call<OpenWeather> call, Response<OpenWeather> response) {
                data.postValue(response.body());
                Log.i(TAG,"API CONNECT SUCCESS");
            }

            @Override
            public void onFailure(Call<OpenWeather> call, Throwable t) {
                Log.d(TAG,"onFailure : "+t.getMessage());
            }
        });
    }
}

 

4. API 호출 완료후 순서에 따라 MainActivity로 이동.

 

5. onResponse()가 호출시 LiveData의 값이 변경이 되서 MainActivity(View)의 onChanged() 호출

        //ViewModel로부터 값을 LiveData를 가져온후 해당 값에 변경사항이 있을때 아래 함수를 호출하게 된다.
        mavm.getWeather().observe(this, new Observer<OpenWeather>() {
            @Override
            public void onChanged(OpenWeather openWeather) {
                Log.i(TAG,"API Connection finish");
                opw = mavm.getWeather().getValue();
                Log.i(TAG,opw.toString());
            }
        });

 

 

이렇게 되면 MVVM을 통해서 API 호출이 완료되게 된다.

반응형