diff --git a/starter/app/build.gradle b/starter/app/build.gradle index 724dd51d8..ce143cf0b 100644 --- a/starter/app/build.gradle +++ b/starter/app/build.gradle @@ -52,6 +52,9 @@ dependencies { implementation "com.squareup.retrofit2:converter-moshi:$version_retrofit" implementation "com.squareup.retrofit2:converter-scalars:$version_retrofit" + // Retrofit + OkHttp + implementation("com.squareup.okhttp3:logging-interceptor:3.5.0") + // Moshi implementation "com.squareup.moshi:moshi:$version_moshi" implementation "com.squareup.moshi:moshi-kotlin:$version_moshi" diff --git a/starter/app/src/main/java/com/udacity/asteroidradar/BindingAdapters.kt b/starter/app/src/main/java/com/udacity/asteroidradar/BindingAdapters.kt index 37d1779bb..372bba262 100644 --- a/starter/app/src/main/java/com/udacity/asteroidradar/BindingAdapters.kt +++ b/starter/app/src/main/java/com/udacity/asteroidradar/BindingAdapters.kt @@ -2,7 +2,9 @@ package com.udacity.asteroidradar import android.widget.ImageView import android.widget.TextView +import androidx.core.net.toUri import androidx.databinding.BindingAdapter +import com.bumptech.glide.Glide @BindingAdapter("statusIcon") fun bindAsteroidStatusImage(imageView: ImageView, isHazardous: Boolean) { @@ -39,3 +41,15 @@ fun bindTextViewToDisplayVelocity(textView: TextView, number: Double) { val context = textView.context textView.text = String.format(context.getString(R.string.km_s_unit_format), number) } + +@BindingAdapter("asteroidPictureOfDay") +fun bindImage(imgView: ImageView, imgUrl: String?) { + imgUrl?.let { + val imgUri = imgUrl.toUri().buildUpon().scheme("https").build() + Glide.with(imgView.context) + .load(imgUri) + .into(imgView) + } +} + + diff --git a/starter/app/src/main/java/com/udacity/asteroidradar/PictureOfDay.kt b/starter/app/src/main/java/com/udacity/asteroidradar/PictureOfDay.kt index ff2039452..f6cf18ddd 100644 --- a/starter/app/src/main/java/com/udacity/asteroidradar/PictureOfDay.kt +++ b/starter/app/src/main/java/com/udacity/asteroidradar/PictureOfDay.kt @@ -4,7 +4,9 @@ import com.squareup.moshi.Json data class PictureOfDay( @Json(name = "media_type") - val mediaType: String, - val title: String, - val url: String + val mediaType: String = "", + @Json(name = "title") + val title: String = "", + @Json(name = "url") + val url: String = "" ) \ No newline at end of file diff --git a/starter/app/src/main/java/com/udacity/asteroidradar/api/NeoWsService.kt b/starter/app/src/main/java/com/udacity/asteroidradar/api/NeoWsService.kt index 418109585..c154c9a69 100644 --- a/starter/app/src/main/java/com/udacity/asteroidradar/api/NeoWsService.kt +++ b/starter/app/src/main/java/com/udacity/asteroidradar/api/NeoWsService.kt @@ -6,6 +6,9 @@ import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import com.udacity.asteroidradar.Constants.BASE_URL import com.udacity.asteroidradar.PictureOfDay +import java.util.concurrent.TimeUnit +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Response import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory @@ -16,28 +19,35 @@ class NeoWsService { val API_KEY = "" + private val interceptor = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY) + private val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .build() + + private val okHttp = OkHttpClient.Builder() + .callTimeout(10, TimeUnit.SECONDS) + .connectTimeout(10, TimeUnit.SECONDS) + .addNetworkInterceptor(interceptor) + .build() + private val moshiRetrofit = Retrofit.Builder() //.addCallAdapterFactory(RxJava3CallAdapterFactory.create()) .addConverterFactory(MoshiConverterFactory.create(moshi)) .baseUrl(BASE_URL) + .client(okHttp) .build() private val neoWsApi : NeoWsApi by lazy { moshiRetrofit.create(NeoWsApi::class.java) } - suspend fun fetchLast() { //}: LiveData { - try { - val foo = neoWsApi.fetchPictureOfDay(API_KEY) - } - catch (e: Exception) { - e.printStackTrace() + suspend fun fetchPictureOfDay() : PictureOfDay? { + neoWsApi.fetchPictureOfDay(API_KEY).apply { + return if (isSuccessful) { + body() + } else { null } } - //foo.i - //return neoWsApi.fetchPictureOfDay(API_KEY) } interface NeoWsApi { @@ -48,6 +58,6 @@ class NeoWsService { @GET("/planetary/apod") suspend fun fetchPictureOfDay( @Query("api_key") apiKey : String - ): PictureOfDay + ): Response } } \ No newline at end of file diff --git a/starter/app/src/main/java/com/udacity/asteroidradar/main/MainFragment.kt b/starter/app/src/main/java/com/udacity/asteroidradar/main/MainFragment.kt index d5068b9f5..fe8b74ee6 100644 --- a/starter/app/src/main/java/com/udacity/asteroidradar/main/MainFragment.kt +++ b/starter/app/src/main/java/com/udacity/asteroidradar/main/MainFragment.kt @@ -18,21 +18,16 @@ class MainFragment : Fragment(), MenuProvider { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) requireActivity().addMenuProvider(this, this, Lifecycle.State.RESUMED) - - viewModel.getLatest() } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { - val binding = FragmentMainBinding.inflate(inflater) - binding.lifecycleOwner = this - - binding.viewModel = viewModel - - - - return binding.root - } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = FragmentMainBinding.inflate(inflater).apply { + lifecycleOwner = this@MainFragment + viewModel = this@MainFragment.viewModel + }.root override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { menuInflater.inflate(R.menu.main_overflow_menu, menu) diff --git a/starter/app/src/main/java/com/udacity/asteroidradar/main/MainRepository.kt b/starter/app/src/main/java/com/udacity/asteroidradar/main/MainRepository.kt index e7b54eb9e..abc13b93a 100644 --- a/starter/app/src/main/java/com/udacity/asteroidradar/main/MainRepository.kt +++ b/starter/app/src/main/java/com/udacity/asteroidradar/main/MainRepository.kt @@ -1,20 +1,18 @@ package com.udacity.asteroidradar.main +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.udacity.asteroidradar.PictureOfDay import com.udacity.asteroidradar.api.NeoWsService class MainRepository { - val neoWsService = NeoWsService() + private val _neoWsService = NeoWsService() + private val _pictureOfDay = MutableLiveData() - suspend fun fetchLatest() { - println("*** fetchLatest") - try { - val list = neoWsService.fetchLast() - println("*** list $list") - } - catch (e : Exception) { - e.printStackTrace() - } + val pictureOfDay : LiveData = _pictureOfDay + suspend fun updateImageOfDay() { + _pictureOfDay.value = _neoWsService.fetchPictureOfDay() } } \ No newline at end of file diff --git a/starter/app/src/main/java/com/udacity/asteroidradar/main/MainViewModel.kt b/starter/app/src/main/java/com/udacity/asteroidradar/main/MainViewModel.kt index 17e42899c..d14bcc53d 100644 --- a/starter/app/src/main/java/com/udacity/asteroidradar/main/MainViewModel.kt +++ b/starter/app/src/main/java/com/udacity/asteroidradar/main/MainViewModel.kt @@ -1,26 +1,29 @@ package com.udacity.asteroidradar.main +import androidx.lifecycle.LiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.udacity.asteroidradar.PictureOfDay import kotlinx.coroutines.launch class MainViewModel : ViewModel() { - val repo = MainRepository() + private val repo = MainRepository() init { - getLatest() + refreshPictureOfDay() } - fun getLatest() { + val pictureOfDay : LiveData = repo.pictureOfDay + + fun refreshPictureOfDay() { viewModelScope.launch { try { - repo.fetchLatest() + repo.updateImageOfDay() } catch (e: Exception) { e.printStackTrace() } } } - } \ No newline at end of file diff --git a/starter/app/src/main/res/layout/fragment_main.xml b/starter/app/src/main/res/layout/fragment_main.xml index a464e97fa..26e57873c 100644 --- a/starter/app/src/main/res/layout/fragment_main.xml +++ b/starter/app/src/main/res/layout/fragment_main.xml @@ -28,6 +28,7 @@ android:layout_height="match_parent" android:adjustViewBounds="true" android:scaleType="centerCrop" + app:asteroidPictureOfDay="@{viewModel.pictureOfDay.url}" app:srcCompat="@drawable/placeholder_picture_of_day"/>