skip to Main Content

I’m having problems getting data from the Facebook API inside a varaiable. In my main activity I call viewModel.getFeed(). The logger returns null, but OkHttp returns the response I want. How can I populate the list with this response data?

FacebookAPIService

interface FacebookAPIService {
    // Get all the english movies in given year
    @GET("USER_ID/feed?access_token=ACCESS_TOKEN")
    fun getUserFeed(): Call<NewsItemData>
}

FacebookAPI

class FacebookAPI {
    companion object {

        private const val baseUrl = "https://graph.facebook.com/v5.0/"

        /**
         * @return [FacebookAPIService] The service class off the retrofit client
         */
        fun createApi(): FacebookAPIService {

            val okHttpClient = OkHttpClient.Builder()
                .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                .build()

            // Create retrofit instance
            val facebookApi = Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .build()

            // Return the retrofit FacebookAPIService
            return facebookApi.create(FacebookAPIService::class.java)
        }
    }
}

NewsRepository

class NewsRepository(context: Context) {
    private val facebookApi: FacebookAPIService = FacebookAPI.createApi()

    fun getUserFeed() = facebookApi.getUserFeed()
...

MainActivityViewModel

class MainActivityViewModel(application: Application) : AndroidViewModel(application) {
    private val newsItemsRepository = NewsRepository(application.applicationContext)
    val newsItems = MutableLiveData<List<NewsItem>>()

    private fun getFeed() {
        newsItemsRepository.getUserFeed().enqueue(object : Callback<NewsItemData?> {
            override fun onResponse(call: Call<NewsItemData?>, response: Response<NewsItemData?>) {
                if (response.isSuccessful) {
                    newsItems.value = response.body()!!.results
                    Log.d("response", newsItems.value.toString())
                } else {
                    error.value = "An error has occurred: ${response.errorBody().toString()}"
                    Log.e("response", response.toString())
                }
            }

            override fun onFailure(call: Call<NewsItemData?>, t: Throwable) {
                error.value = t.message
            }
        })
    }
}

NewsItem

@Parcelize
@Entity(tableName = "news_item")
data class NewsItem(
    @SerializedName("message") var message: String,
    @SerializedName("story") var story: String,
    @PrimaryKey(autoGenerate = true) val id: Long? = null
) : Parcelable

NewsItemData

class NewsItemData {
    var results: List<NewsItem>? = null
}

To give some more background my response looks something like this:

{
   "data": [
      ...
      {
         "created_time": "some timestamp",
         "id": "some id"
      },
      {
         "message": "some messge",
         "created_time": "some timestamp",
         "id": "some id"
      }
      ...
   ],
   "paging": {
       ...
    }
}

2

Answers


  1. This my code for response parse json

    if (response.isSuccessful) {
        response.body()?.let { body ->
            results=body
            Log.d("API RESULT"," $results")
        }
    } else {
        var bodyError=response.errorBody()?.string()?:"Error connection with server"
        try {
            //use this to parse json at error response
            val message=JSONObject(bodyError)
            bodyError = if (message.has("message")) 
                            message.getString("message")
                        else 
                            "Error connection with server"
        }catch (ex: JSONException) {
            Log.e("API NOT JSON"," $bodyError")
        }
        Log.e("API ERROR"," $bodyError")
    }
    

    Hope this help

    Login or Signup to reply.
  2. The problem here is that you have to add a @SerializedName to the NewsItemData results field.

    NewsItemData

    class NewsItemData {
        @SerializedName("data") var results: List<NewsItem>? = null
    }
    

    Otherwise the JSON array won’t be correctly mapped to a list as you intended.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search