0

I want to call api using rxjava3 inside getCampaigns function in CampaignRepositoryImpl.kt class but I am getting following error error A 'return' expression required in a function with a block body ('{...}')

below CampaignRepositoryImpl.kt class

import de.westwing.campaignbrowser.domain.Campaign
import de.westwing.campaignbrowser.domain.CampaignRepository
import io.reactivex.rxjava3.core.Single

class CampaignRepositoryImpl(private val apiInterface: ApiInterface) : CampaignRepository {

    override fun getCampaigns(): Single<List<Campaign>> {

       apiInterface.getCampaigns()

    }

}

below my interface class I am getting API call

interface ApiInterface {

    @GET("cms/test/campaigns.json")
    fun getCampaigns(): Single<CampaignsResponse>

}

below CampaignRepository

interface CampaignRepository {

fun getCampaigns(): Single<List<Campaign>>

}

below my CompaignResponse.kt

data class CampaignsResponse(val metadata: CampaignsMetadata)

below CampaingsMetadata

data class CampaignsMetadata(val data: List<CampaignDto>)

below

data class Campaign(val name: String, val description: String)

below CampaignDto

class CampaignDto(val name: String, val description: String, val image: ImageDto)

I want to know where I am making mistake what I have to do in order to avoid error

  • Err, you need to return something from the function? `return apiInterface.getCampaigns()` – broot Jul 02 '21 at 17:05
  • even I am returning I am getting the same error – Jack Philips Jul 02 '21 at 17:07
  • @broot I am doing as exactly as you told but I am getting following error Type mismatch. Required: Single> Found: Single – Jack Philips Jul 02 '21 at 17:09
  • Yes, but this error message is also quite descriptive. Your `ApiInterface.getCampaigns()` returns `Single`, but you need to return `Single>` from outer function, so you need to convert first to the second one. I guess `CampaignResponse` contains `List` somewhere inside. – broot Jul 02 '21 at 17:11
  • @broot can you explain your answer with coding sample – Jack Philips Jul 02 '21 at 17:14
  • @broot I have tried both answer it did not work even I have added additional code – Jack Philips Jul 02 '21 at 17:36
  • Answer of Ben P. is really good. It is not easy to provide you a fully working example, because we can't know how to convert `CampaignsResponse` to `List`. This is your code, your data structures and only you can know how to do this. You can provide the definition of `CampaignsResponse` and `Campaign`. Hopefully, `List` is somewhere inside `CampaignsResponse` and then it will be easy. If not then it really depends on your specific data structures. – broot Jul 02 '21 at 17:46
  • I have added fullcoding structure and I have added my response – Jack Philips Jul 02 '21 at 17:47
  • @broot what additional classes do you need – Jack Philips Jul 02 '21 at 17:48
  • As I said: `CampaignsResponse` and `Campaign` classes. Your problem is really on how to convert the first to the second. We can't know this if we don't even know what is `CampaignsResponse` and `Campaign`. – broot Jul 02 '21 at 17:51
  • Ahh, sorry, you provided `CampaignsResponse`. But again, there is only some `CampaignsMetadata` object inside. We don't know what it is. – broot Jul 02 '21 at 17:52
  • Ahh, we are almost there, `CampaignDto` please... :-D – broot Jul 02 '21 at 17:59
  • @broot added d)) – Jack Philips Jul 02 '21 at 18:03
  • Well, something didn't work, the code is missing. – broot Jul 02 '21 at 18:04
  • @broot I want to know what is missing – Jack Philips Jul 02 '21 at 18:05
  • @broot let me know if you need more classes – Jack Philips Jul 02 '21 at 18:06
  • I mean you just added "below CampaignDto", but there is no `CampaignDto` below. For your information, I don't ask for all these classes to annoy you. We really need to use all of them here ;-) – broot Jul 02 '21 at 18:06
  • @broot sorry I have added my mistake d)) – Jack Philips Jul 02 '21 at 18:08
  • Ok, I think now we have everything. Take Ben P. answer and replace `it.campaigns` with: `it.metadata.data.map { Campaign(it.name, it.description) }`. I believe (but only believe) that it should at least compile. – broot Jul 02 '21 at 18:10
  • @broot thank you so much it is working tack a mycket it means thank you in swedish – Jack Philips Jul 02 '21 at 18:13
  • I'm glad it worked. But I think you really need to understand what your own code does and try to work with it by yourself. As you can see, it is not that easy to provide a fully working example remotely, it requires knowing half of your existing codebase. Converting one class to another with almost the same fields is pretty much basics. – broot Jul 02 '21 at 18:14
  • okay I will do as you toldme – Jack Philips Jul 02 '21 at 18:17
  • @broot can you check mu other question as well – Jack Philips Jul 03 '21 at 23:41

2 Answers2

2

From your api interface, we can see that the type of getCampaigns() is Single<CampaignsResponse>. In your repository implementation, on the other hand, the type of getCampaigns() is Single<List<Campaign>>.

Since both are Single<Foo>, you'll need to map from one to the other.

Given your class implementations, this should work:

override fun getCampaigns(): Single<List<Campaign>> {
   return apiInterface.getCampaigns().map { response ->
       response.metadata.data.map {
           Campaign(it.name, it.description)
       }
   }
}

This map call is taking a CampaignResponse and turning it into a List<Campaign>.

Ben P.
  • 52,661
  • 6
  • 95
  • 123
  • can you check my updated code I am getting following error – Jack Philips Jul 02 '21 at 17:25
  • Your screenshot shows an `entity` package with `CampaignResponse` and `CampaignMetadata`, as well as a `domain` package with `Campaign`. We'd need to see the contents of those files to provide any more details. – Ben P. Jul 02 '21 at 17:47
  • I have added CampaignResponse and CampaignMetadata, as well as a domain package with Campaign – Jack Philips Jul 02 '21 at 17:54
  • @BenP. Please replace `it.campaigns` in your answer with: `it.metadata.data.map { Campaign(it.name, it.description) }` - just for future readers. – broot Jul 02 '21 at 18:16
0

Since your ApiInterface returns Single, you can just return it in method body. You might have to check out that CampaignRepository has getCampaigns() method and it should return Single.

    class CampaignRepositoryImpl(private val apiInterface: ApiInterface) : CampaignRepository {
    
        override fun getCampaigns(): Single<CampaignsResponse> {
    
           return apiInterface.getCampaigns()
    
        }
    
    }
JustinB
  • 45
  • 7