I followed everything carefully, step by step, but I can't find what the problem is. Whenever I fill in the name of the movie I intend to search by, the app crashes and it says this: java.lang.NullPointerException: response.body() must not be null
Does anyone have any idea? Here is the following code.
MovieList.kt
class MovieList {
val imdbID: String
val Title: String
val Year: String
val Plot: String
val Poster: String
constructor(imdbID: String, Title: String, Year: String, Plot: String, Poster: String) {
this.imdbID = imdbID
this.Title = Title
this.Year = Year
this.Plot = Plot
this.Poster = Poster
}
}
OMDbApi.kt
interface OMDbApi {
@GET("t={Title}")
fun getMovieByTitle(@Path("Title") Title: String): Call<MovieList>
}
OMDbApiClient.kt
class OMDbApiClient {
companion object{
private var omdbapi: OMDbApi? = null
fun getOMDbApi(): OMDbApi?{
if(omdbapi == null){
omdbapi = Retrofit.Builder()
.baseUrl("http://www.omdbapi.com/?&apikey=eb73867f")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(OMDbApi::class.java);
}
return omdbapi
}
}
}
FirstFragment.kt
class FirstFragment : Fragment() {
private lateinit var omdbapiClient: OMDbApi
private lateinit var tvMovieTitle: TextView
private lateinit var ivImagePoster: ImageView
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_first, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
omdbapiClient = OMDbApiClient.getOMDbApi()!!
val movieId: EditText = view.findViewById<EditText>(R.id.TitleId)
tvMovieTitle = view.findViewById(R.id.MovieTitleId)
ivImagePoster = view.findViewById(R.id.MoviePosterId)
movieId.setOnEditorActionListener { v, actionId, event ->
if(actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_NEXT){
val movietitle: String = movieId.text.toString()
searchMovieByTitle(movietitle)
true
}
else{
Toast.makeText(activity, "Error!", Toast.LENGTH_LONG).show()
false
}
}
}
private fun searchMovieByTitle(movietitle: String) {
omdbapiClient.getMovieByTitle(movietitle).enqueue(object : Callback<MovieList>{
override fun onResponse(call: Call<MovieList>?, response: Response<MovieList>) {
displayData(response.body())
Toast.makeText(activity, "Success!", Toast.LENGTH_LONG).show()
}
override fun onFailure(call: Call<MovieList>?, t: Throwable?) {
Toast.makeText(activity, "Error!", Toast.LENGTH_LONG).show()
}
})
}
private fun displayData(data: MovieList) {
tvMovieTitle.text = data.Title
Glide.with(this).load(data.Poster).into(ivImagePoster)
}
}
I think you are getting an error response and that's why the response.body()
is null
. You should be handling an error response gracefully, instead of expecting the body to always not be null, but that is another matter.
I think the following lines of code are at fault:
interface OMDbApi {
@GET("t={Title}")
fun getMovieByTitle(@Path("Title") Title: String): Call<MovieList>
}
The 'Title' should be a @Query
parameter instead of a @Path
parameter, because the &t=
part in the API url is a query parameter. When it is a query parameter you also don't specify it as part of the path in @GET
.
Your code would then become:
interface OMDbApi {
@GET("")
fun getMovieByTitle(@Query("t") title: String): Call<MovieList>
}
Do this change and see if you still get an error response. You might want to check the log in the 'Logcat' tab to see what error you are getting back from the API.
For that you might have to enable a higher logging level. This is done by adding a logging interceptor when building the Retrofit client.
// Build a http client with logging enabled
val client = OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().apply {
// you can also use Level.BODY for even more log information
level = HttpLoggingInterceptor.Level.BASIC
})
.build()
omdbapi = Retrofit.Builder()
.client(client) // add this line to use your http client
.baseUrl("http://www.omdbapi.com/?&apikey=eb73867f")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(OMDbApi::class.java);