BRDroid
BRDroid

Reputation: 4388

Queuing/saving retrofit requests and send them later when there is poor/no internet connection

I have my android application which is not build to work offline, so it is reliant on network connection/data.

App makes a lot of network calls updating the api with new set of data.

I am making changes in it to make it work offline.

Approach I am thinking I will create a Room data base in which I will save the retrofit requests and when there is connection I will pull them from the data base and send it to the api.

does that sound right? Is there any other better approach, where I can save requests when there is no connection and when there is connection send those saved requests to the server.

Also can we save requests in Room database

I am not intending on doing database synchronisation with BE(API) and BE(API) deals with requests.

your suggestions are valuable

Thanks R

Upvotes: 4

Views: 1483

Answers (2)

faribakhandani
faribakhandani

Reputation: 49

Following below steps to create this request with MVVM and Room in retrofit : First of all : Create a table for saving offline data and with Dao interface,you can create insert and Query functions such as below (the reason for using suspend is that it indicates the method can be used in coroutine scop for handling asynchronous operations):

interface DaoOffInfo {

    @Insert
    suspend fun insertOffInfo(newsOffInfo: NewsOffInfo)

    @Query("SELECT*FROM newsoffinfo")
    fun getAllNews():LiveData<List<NewsOffInfo>>
}

the second step in ViewModel create an insert method to save data from retrofit:

fun getAllNews(category:String){
          CoroutineScope(Dispatchers.IO).launch {
              var response =repositoryNews.getAllNews(category)

              withContext(Dispatchers.Main){



                  if(response.isSuccessful){


                      newslist.postValue(response.body()!!)
                          response.body()!!.articles
                    

                     for (i in response.body()!!.articles.indices){
                         name= response.body()!!.articles.get(i).title
                         desc = response.body()!!.articles.get(i).description
                          date = response.body()!!.articles.get(i).publishedAt
                         content = response.body()!!.articles.get(i).content

                         if(desc.isNullOrEmpty()){
                             desc = "There is no Description for this article."
                         }
                         if(content.isNullOrEmpty()){
                             content = "There is no Content for this article."
                         }



                      }

                       insertData(NewsOffInfo(0,name, desc.toString(),date,content.toString()))
                  }


                      }
                  }


          }

and val allNews =repositoryOffLine.allNewsInfo ,infact read the data from database then in activity or fragment for handling internet connection using connectivityManager and this methods :

  private fun isNetworkAvailable(): Boolean { 
connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

            val networkInfo = connectivityManager.activeNetworkInfo
            return networkInfo != null && networkInfo.isConnected
        }

Finally here checking the internet is connected or not :

 private fun updateRecyclerViews(){

        if(isNetworkAvailable()) {

          //if internet is connected 
}
else {
      //no internet connection ,read the data from room and display which means that with allnews that created to read from database ,we can observe the values.

 

    viewModelRetrofit.allNews.observe()...

}
}

Upvotes: 0

sergiy tykhonov
sergiy tykhonov

Reputation: 5103

At once I want to say - I think what you ask is not very good idea and I can't recommend do like that. But it's your choice. What came into my mind as for saving requests in Room (maybe is oddity, but let it be):

  1. Let's assume you have N api endpoints. Each of them has some parameters (from 0 to M).
  2. You can make a table requests in your Room, that contains (1 + P) columns, where P - maximal amount of your endpoints' parameters (maybe there should be date for chronology and a mark whether request was already processed as well). All columns have String type. First column - is for endpoints name (key). That key you will use to define with it one of your Retrofit endpoints.
  3. In offline mode you save your request in table requests' row - name for endpoint and serialised to JSON string for each parameter.
  4. When network is on - you query your table, deserialise your api parameters and in some loop recreate your rest Api requests in some huge when-statement like that:

    // restApi - your Retrofit interface // apiName - endpoint String key from db // parameter1 - endpoint's parameter1, restored from db saved JSON string // .... // parameterM - endpoint's parameterM, restored from db saved JSON string when (apiName) { "endpoint1" -> restApi.someYourEndPoint1(parameter1) "endpoint2" -> restApi.someYourEndPoint2(parameter1,parameter2) .......... }

Upvotes: 1

Related Questions