recyclerview not showing data?

怎甘沉沦 提交于 2019-12-13 11:25:36

问题


I am developing news app I am new to MVVM and I have implemented Kotlin coroutines and Koin with ViewModel hosted RecyclerView in fragment class but data not showing only progress bar loading

below my screenshot

I have posted my code to gist

my code on gist

below my code where I have implemented recyclerview and viewmodel logic

class TopHeadlinesFragment : Fragment() {

private val viewModel: MainViewModel by viewModel()
private lateinit var topHeadlinesAdapter: TopHeadlinesAdapter


//3
override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val view = inflater.inflate(
        R.layout.fragment_top_headlines
        , container, false
    )


    val recyclerView = view.findViewById(R.id.recyclerView) as RecyclerView
    val pb = view.findViewById(R.id.pb) as ProgressBar
    topHeadlinesAdapter = TopHeadlinesAdapter(recyclerView.context)
    recyclerView.layoutManager = LinearLayoutManager(context)
    recyclerView.adapter = topHeadlinesAdapter
    initViewModel()

    return view
}

private fun initViewModel() {
    viewModel?.sportList?.observe(this, Observer { newList ->
        topHeadlinesAdapter.updateData(newList)
    })

    viewModel?.showLoading?.observe(this, Observer { showLoading ->
        pb.visibility = if (showLoading) View.VISIBLE else View.GONE
    })

    viewModel?.showError?.observe(this, Observer { showError ->
        (showError)
    })

    viewModel?.loadNews()
}

}

below ViewModel class

class MainViewModel(newsRepository: NewsRepository) : ViewModel() CoroutineScope {
    // Coroutine's background job
     val job = Job()
     val sportNewsInterface: SportNewsInterface? = null
    // Define default thread for Coroutine as Main and add job
    override val coroutineContext: CoroutineContext = Dispatchers.Main + job

     val showLoading = MutableLiveData<Boolean>()
     val sportList = MutableLiveData <List<Article>>()
    val showError = SingleLiveEvent<String>()



    fun loadNews(

    ) {
        // Show progressBar during the operation on the MAIN (default) thread
        showLoading.value = true
        // launch the Coroutine
        launch {
            // Switching from MAIN to IO thread for API operation
            // Update our data list with the new one from API
            val result = withContext(Dispatchers.IO) {
                sportNewsInterface?.getNews()
            }
            // Hide progressBar once the operation is done on the MAIN (default) thread
            showLoading.value = false
            when (result) {

                is UseCaseResult.Success<*> -> {
                    sportList.value = result.data as List<Article>
                }
                is Error -> showError.value = result.message
            }
        }


    }

    override fun onCleared() {
        super.onCleared()
        // Clear our job when the linked activity is destroyed to avoid memory leaks
        job.cancel()
    }
}

below repository class

    interface NewsRepository {
        // Suspend is used to await the result from Deferred
        suspend fun getNewsList(): UseCaseResult<List<Article>>
    }

    class NewsRepositoryImpl(private val sportNewsInterface: SportNewsInterface) : NewsRepository {
        override suspend fun getNewsList(): UseCaseResult<List<Article>> {

            return try {
                val result = sportNewsInterface.getNews()
                UseCaseResult.Success(result) as UseCaseResult<List<Article>>
            } catch (ex: Exception) {
                UseCaseResult.Error(ex)
            }
        }
    }

below appModules.kt where I have implemented network logic

const val BASE_URL = "https://newsapi.org/"

val appModules = module {
    // The Retrofit service using our custom HTTP client instance as a singleton
    single {
        createWebService<SportNewsInterface>(
            okHttpClient = createHttpClient(),
            factory = RxJava2CallAdapterFactory.create(),
            baseUrl = BASE_URL
        )
    }
    // Tells Koin how to create an instance of CatRepository
    factory<NewsRepository> { (NewsRepositoryImpl(sportNewsInterface = get())) }
    // Specific viewModel pattern to tell Koin how to build MainViewModel
    viewModel { MainViewModel (newsRepository = get ())  }
}

/* Returns a custom OkHttpClient instance with interceptor. Used for building Retrofit service */
fun createHttpClient(): OkHttpClient {
    val client = OkHttpClient.Builder()
    client.readTimeout(5 * 60, TimeUnit.SECONDS)
    return client.addInterceptor {
        val original = it.request()
        val requestBuilder = original.newBuilder()
        requestBuilder.header("Content-Type", "application/json")
        val request = requestBuilder.method(original.method, original.body).build()
        return@addInterceptor it.proceed(request)
    }.build()
}

/* function to build our Retrofit service */
inline fun <reified T> createWebService(
    okHttpClient: OkHttpClient,
    factory: CallAdapter.Factory, baseUrl: String
): T {
    val retrofit = Retrofit.Builder()
        .baseUrl(baseUrl)
        .addConverterFactory(GsonConverterFactory.create(GsonBuilder().setLenient().create()))
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .addCallAdapterFactory(factory)
        .client(okHttpClient)
        .build()
    return retrofit.create(T::class.java)
}

below my ending points interface SportNewsInterface {

@GET("v2/top-headlines?country=us&apiKey=da331087e3f3462bb534b3b0917cbee9")
suspend fun getNews(): List<SportNewsResponse>

@GET("/v2/top-headlines?sources=espn&apiKey=da331087e3f3462bb534b3b0917cbee9")
fun getEspn(): Deferred<List<SportNewsResponse>>

@GET("/v2/top-headlines?sources=football-italia&apiKey=da331087e3f3462bb534b3b0917cbee9")
fun getFootballItalia(): Deferred<List<SportNewsResponse>>

@GET("/v2/top-headlines?sources=bbc-sport&apiKey=da331087e3f3462bb534b3b0917cbee9")
fun getBBCSport(): Deferred<List<SportNewsResponse>>

}

below my Koin Initialization

class SportNewsApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        // Adding Koin modules to our application
        startKoin {
            androidContext(this@SportNewsApplication)
            modules(appModules)
        }
    }
}

来源:https://stackoverflow.com/questions/59136748/recyclerview-not-showing-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!