进度条加载不显示来自服务器的响应?
progress bar loading not showing response from server?
我正在开发新闻应用程序,但 TopHeadlinesFragment 加载进度条未显示来自服务器的响应
我想知道我在哪里犯错 我必须做什么才能显示服务器的响应。也许我在 topHeadlinesFragment.kt 或 koin 网络模块
中的观察者有问题
在我的应用截图下方
loading progress
低于我的TopHeadlinesFragment.kt
class TopHeadlinesFragment : Fragment() {
private lateinit var binding: FragmentTopHeadlinesBinding
private val viewModel by viewModel<MainViewModel>()
private lateinit var topHeadlinesAdapter: TopHeadlinesAdapter
// private val newsRepository: NewsRepository by inject()
//3
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding =
DataBindingUtil.inflate(inflater, R.layout.fragment_top_headlines, container, false)
binding.lifecycleOwner = this
topHeadlinesAdapter = TopHeadlinesAdapter()
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViewModel()
// loadingAds()
}
private fun initViewModel() {
viewModel.sportList.observe(this, Observer { result ->
when (result) {
is Results.Success -> {
val newList = result.data
if (newList != null) {
topHeadlinesAdapter.updateData(newList)
}
binding.recyclerView.adapter = topHeadlinesAdapter
topHeadlinesAdapter.notifyDataSetChanged()
viewModel.showLoading.observe(this, Observer {showLoading ->
pb.visibility = if (showLoading) View.VISIBLE else View.GONE
})
}
is Results.Failure -> {
viewModel.showLoading.observe(this, Observer {showLoading ->
pb.visibility = if (showLoading) View.INVISIBLE else View.GONE
})
}
}
viewModel.loadNews()
})
}
}
低于NewsRepository.kt
class NewsRepository(
private val sportNewsApi: SportNewsInterface,
private val sportNewsDao: SportNewsDao
) {
companion object{
const val TAG= "Error"
}
val data = sportNewsDao.getAllData()
suspend fun refresh() = withContext(Dispatchers.IO) {
val articles = sportNewsApi.getNewsAsync().body()?.articles
if (articles != null) {
sportNewsDao.addAll(articles)
Log.e(TAG,"Error")
Results.Success(articles)
} else {
Results.Failure("MyError")
}
}
}
低于我的 MainViewModel.kt
class MainViewModel(val newsRepository: NewsRepository) : ViewModel(), CoroutineScope {
// Coroutine's background job
val job = Job()
// Define default thread for Coroutine as Main and add job
override val coroutineContext: CoroutineContext = Dispatchers.Main + job
private val _showLoading = MutableLiveData<Boolean>()
private val _sportList = MutableLiveData<Results>()
val showLoading: LiveData<Boolean>
get() = _showLoading
val sportList: LiveData<Results>
get() = _sportList
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 = newsRepository.refresh()
_sportList.value = result
_showLoading.value = false
}
}
override fun onCleared() {
job.cancel()
}
}
低于我的 KoinNetworkModule.kt
const val BASE_URL = "https://newsapi.org/"
val netModule = module {
single {
createWebService<SportNewsInterface>(
okHttpClient = createHttpClient(),
factory = RxJava2CallAdapterFactory.create(),
baseUrl = BASE_URL
)
}
}
/* 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)
}
找到你的问题了。如果你真的想显示响应,无论你得到什么,都可以在 Retrofit 实例中使用此代码。 Intercepter 的作用是在 Log 层面展示请求和响应。您可以在日志 window.
中找到 API 的 URL,请求和响应
现在像这样修改KoinNetworkModule.kt
const val BASE_URL = "https://newsapi.org/"
val netModule = module {
single {
createWebService<SportNewsInterface>(
okHttpClient = createHttpClient(),
factory = RxJava2CallAdapterFactory.create(),
baseUrl = BASE_URL
)
}
}
/* Returns a custom OkHttpClient instance with interceptor. Used for building Retrofit service */
fun createHttpClient(): OkHttpClient {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client1 = OkHttpClient.Builder()
.connectTimeout(2, TimeUnit.MINUTES)
.writeTimeout(2, TimeUnit.MINUTES) // write timeout
.readTimeout(2, TimeUnit.MINUTES) // read timeout
.addInterceptor(interceptor)
.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(client1)
.build()
return retrofit.create(T::class.java)
}
我通过更改我的代码解决了问题。
private fun initViewModel() {
viewModel.sportList.observe(this, Observer { result ->
when (result) {
is Results.Success -> {
val newList = result.data
if (newList != null) {
topHeadlinesAdapter.updateData(newList)
}
binding.recyclerView.adapter = topHeadlinesAdapter
topHeadlinesAdapter.notifyDataSetChanged()
}
}
})
viewModel.showLoading.observe(this, Observer { showLoading ->
pb.visibility = if (showLoading) View.VISIBLE else View.GONE
})
viewModel.loadNews()
}
我正在开发新闻应用程序,但 TopHeadlinesFragment 加载进度条未显示来自服务器的响应 我想知道我在哪里犯错 我必须做什么才能显示服务器的响应。也许我在 topHeadlinesFragment.kt 或 koin 网络模块
中的观察者有问题在我的应用截图下方
loading progress
低于我的TopHeadlinesFragment.kt
class TopHeadlinesFragment : Fragment() {
private lateinit var binding: FragmentTopHeadlinesBinding
private val viewModel by viewModel<MainViewModel>()
private lateinit var topHeadlinesAdapter: TopHeadlinesAdapter
// private val newsRepository: NewsRepository by inject()
//3
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding =
DataBindingUtil.inflate(inflater, R.layout.fragment_top_headlines, container, false)
binding.lifecycleOwner = this
topHeadlinesAdapter = TopHeadlinesAdapter()
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViewModel()
// loadingAds()
}
private fun initViewModel() {
viewModel.sportList.observe(this, Observer { result ->
when (result) {
is Results.Success -> {
val newList = result.data
if (newList != null) {
topHeadlinesAdapter.updateData(newList)
}
binding.recyclerView.adapter = topHeadlinesAdapter
topHeadlinesAdapter.notifyDataSetChanged()
viewModel.showLoading.observe(this, Observer {showLoading ->
pb.visibility = if (showLoading) View.VISIBLE else View.GONE
})
}
is Results.Failure -> {
viewModel.showLoading.observe(this, Observer {showLoading ->
pb.visibility = if (showLoading) View.INVISIBLE else View.GONE
})
}
}
viewModel.loadNews()
})
}
}
低于NewsRepository.kt
class NewsRepository(
private val sportNewsApi: SportNewsInterface,
private val sportNewsDao: SportNewsDao
) {
companion object{
const val TAG= "Error"
}
val data = sportNewsDao.getAllData()
suspend fun refresh() = withContext(Dispatchers.IO) {
val articles = sportNewsApi.getNewsAsync().body()?.articles
if (articles != null) {
sportNewsDao.addAll(articles)
Log.e(TAG,"Error")
Results.Success(articles)
} else {
Results.Failure("MyError")
}
}
}
低于我的 MainViewModel.kt
class MainViewModel(val newsRepository: NewsRepository) : ViewModel(), CoroutineScope {
// Coroutine's background job
val job = Job()
// Define default thread for Coroutine as Main and add job
override val coroutineContext: CoroutineContext = Dispatchers.Main + job
private val _showLoading = MutableLiveData<Boolean>()
private val _sportList = MutableLiveData<Results>()
val showLoading: LiveData<Boolean>
get() = _showLoading
val sportList: LiveData<Results>
get() = _sportList
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 = newsRepository.refresh()
_sportList.value = result
_showLoading.value = false
}
}
override fun onCleared() {
job.cancel()
}
}
低于我的 KoinNetworkModule.kt
const val BASE_URL = "https://newsapi.org/"
val netModule = module {
single {
createWebService<SportNewsInterface>(
okHttpClient = createHttpClient(),
factory = RxJava2CallAdapterFactory.create(),
baseUrl = BASE_URL
)
}
}
/* 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)
}
找到你的问题了。如果你真的想显示响应,无论你得到什么,都可以在 Retrofit 实例中使用此代码。 Intercepter 的作用是在 Log 层面展示请求和响应。您可以在日志 window.
中找到 API 的 URL,请求和响应现在像这样修改KoinNetworkModule.kt
const val BASE_URL = "https://newsapi.org/"
val netModule = module {
single {
createWebService<SportNewsInterface>(
okHttpClient = createHttpClient(),
factory = RxJava2CallAdapterFactory.create(),
baseUrl = BASE_URL
)
}
}
/* Returns a custom OkHttpClient instance with interceptor. Used for building Retrofit service */
fun createHttpClient(): OkHttpClient {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client1 = OkHttpClient.Builder()
.connectTimeout(2, TimeUnit.MINUTES)
.writeTimeout(2, TimeUnit.MINUTES) // write timeout
.readTimeout(2, TimeUnit.MINUTES) // read timeout
.addInterceptor(interceptor)
.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(client1)
.build()
return retrofit.create(T::class.java)
}
我通过更改我的代码解决了问题。
private fun initViewModel() {
viewModel.sportList.observe(this, Observer { result ->
when (result) {
is Results.Success -> {
val newList = result.data
if (newList != null) {
topHeadlinesAdapter.updateData(newList)
}
binding.recyclerView.adapter = topHeadlinesAdapter
topHeadlinesAdapter.notifyDataSetChanged()
}
}
})
viewModel.showLoading.observe(this, Observer { showLoading ->
pb.visibility = if (showLoading) View.VISIBLE else View.GONE
})
viewModel.loadNews()
}