Android Architecture Componentsを用いた実装例

この項ではAndroid Architecture Componentsを用いた実装例を紹介します。

ViewModel

RFPに対応するViewModelを実装します。

Context が必要となるので AndroidViewModel を継承します。

    class AdViewModel(app: Application) : AndroidViewModel(app) {
        // ...
    }
    

    実装したViewModelFactoryからRFP用のViewModelを取得します。

      class ArticleFragment : Fragment() {
          private lateinit var adViewModel: AdViewModel
      
          override fun onActivityCreated(savedInstanceState: Bundle?) {
              super.onActivityCreated(savedInstanceState)
      
              // ... ...
      
              adViewModel = ViewModelProviders.of(this)
                      .get(AdViewModel::class.java)
      
              // ... ...
          }
      }
      

      LiveData

      AdViewModel#getAds()でLiveDataを返すように実装します。

        fun getAds(spotId: String, count: Int, positions: List<Int>?)
                : LiveData<AdResponse<List<RFPInstreamInfoModel>>> {
            val repository = AdRepository()
            return repository.getAds(getApplication(), spotId, count, positions)
        }
        

        広告取得の成否を判断するため AdResponse クラスで広告情報をラップしています。

          enum class AdStatus {
              SUCCESS,
              ERROR,
          }
          
          data class AdResponse<out T>(val status: AdStatus, val data: T?, val message: String?) {
              companion object {
                  fun <T> success(data: T?): AdResponse<T> {
                      return AdResponse(AdStatus.SUCCESS, data, null)
                  }
          
                  fun <T> error(msg: String, data: T?): AdResponse<T> {
                      return AdResponse(AdStatus.ERROR, data, msg)
                  }
              }
          }
          

          LiveDataを購読し、結果をUIに反映します。

            override fun onActivityCreated(savedInstanceState: Bundle?) {
                super.onActivityCreated(savedInstanceState)
            
                // ... ...
            
                val positions = listOf(1, 5, 9)
                val count = positions.size
                adViewModel.getAds(spotId, count, positions).observe(this, Observer { response ->
                    response ?: return@Observer
                    if (response.status == AdStatus.ERROR) {
                        // Failed to fetch ads
                        return@Observer
                    }
                    // Update UI
                    val ads = response.data ?: return@Observer
                    // ... ...
                })
            }
            

            広告の取得

            実際の広告取得を行うRepositoryクラスを実装します。

            RFPInstreamAdLoader にリスナーを設定し、onSuccess()onFailure()でLiveDataを変更します。

              class AdRepository {
                  fun getAds(context: Context, spotId: String, count: Int, positions: List<Int>?)
                          : LiveData<AdResponse<List<RFPInstreamInfoModel>>> {
                      val data = MutableLiveData<AdResponse<List<RFPInstreamInfoModel>>>()
              
                      val loader = RFPInstreamAdLoader.Builder(spotId)
                              .count(count)
                              .positions(positions)
                              .onSuccess { items ->
                                  val response = AdResponse.success(items)
                                  data.postValue(response)
                              }
                              .onFailure { message ->
                                  val response = AdResponse.error(message, null)
                                  data.postValue(response)
                              }
                              .build()
                      loader.loadAd(context)
              
                      return data
                  }
              }