Skip to content

Commit cd0c6f9

Browse files
committed
search functionality added
1 parent 73e6e7b commit cd0c6f9

File tree

4 files changed

+98
-0
lines changed

4 files changed

+98
-0
lines changed

app/src/main/java/com/sijanneupane/mvvmnews/repository/NewsRepository.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,10 @@ class NewsRepository(
1414
*/
1515
suspend fun getBreakingNews(countryCode:String, pageNumber:Int)=
1616
RetrofitInstance.api.getBreakingNews(countryCode, pageNumber)
17+
18+
/*
19+
function that query our api for searched news
20+
*/
21+
suspend fun searchNews(searchQuery: String, pageNumber: Int)=
22+
RetrofitInstance.api.searchForNews(searchQuery, pageNumber)
1723
}

app/src/main/java/com/sijanneupane/mvvmnews/ui/NewsViewModel.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ class NewsViewModel(
1515

1616
//LIVEDATA OBJECT
1717
val breakingNews: MutableLiveData<Resource<NewsResponse>> = MutableLiveData()
18+
val searchNews: MutableLiveData<Resource<NewsResponse>> = MutableLiveData()
19+
1820
//Pagination
1921
var breakingNewsPage= 1
22+
var searchNewsPage= 1
2023

2124
init {
2225
getBreakingNews("in")
@@ -34,10 +37,20 @@ class NewsViewModel(
3437

3538
//handling response
3639
breakingNews.postValue(handleBreakingNewsResponse(response))
40+
}
41+
42+
43+
fun searchNews(searchQuery: String)= viewModelScope.launch {
44+
searchNews.postValue(Resource.Loading()) //init loading state before the network call
3745

46+
//actual response
47+
val response= newsRepository.searchNews(searchQuery, searchNewsPage)
3848

49+
//handling response
50+
searchNews.postValue(handleSearchNewsResponse(response))
3951
}
4052

53+
4154
private fun handleBreakingNewsResponse(response: Response<NewsResponse>): Resource<NewsResponse>{
4255
if (response.isSuccessful){
4356
response.body()?.let { resultResponse ->
@@ -47,4 +60,13 @@ class NewsViewModel(
4760
return Resource.Error(response.message())
4861
}
4962

63+
private fun handleSearchNewsResponse(response: Response<NewsResponse>): Resource<NewsResponse>{
64+
if (response.isSuccessful){
65+
response.body()?.let { resultResponse ->
66+
return Resource.Success(resultResponse)
67+
}
68+
}
69+
return Resource.Error(response.message())
70+
}
71+
5072
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,90 @@
11
package com.sijanneupane.mvvmnews.ui.fragments
22

33
import android.os.Bundle
4+
import android.util.Log
45
import android.view.View
6+
import androidx.core.widget.addTextChangedListener
57
import androidx.fragment.app.Fragment
8+
import androidx.lifecycle.Observer
9+
import androidx.recyclerview.widget.LinearLayoutManager
610
import com.sijanneupane.mvvmnews.R
11+
import com.sijanneupane.mvvmnews.adapters.NewsAdapter
712
import com.sijanneupane.mvvmnews.ui.MainActivity
813
import com.sijanneupane.mvvmnews.ui.NewsViewModel
14+
import com.sijanneupane.mvvmnews.utils.Constants.Companion.SEARCH_DELAY
15+
import com.sijanneupane.mvvmnews.utils.Resource
16+
import kotlinx.android.synthetic.main.fragment_search_news.*
17+
import kotlinx.coroutines.Job
18+
import kotlinx.coroutines.MainScope
19+
import kotlinx.coroutines.delay
20+
import kotlinx.coroutines.launch
921

1022
class SearchNewsFragment : Fragment (R.layout.fragment_search_news) {
1123

1224
lateinit var viewModel: NewsViewModel
25+
val TAG= "SearchNewsFragment"
26+
lateinit var newsAdapter: NewsAdapter
1327

1428
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
1529
super.onViewCreated(view, savedInstanceState)
1630

1731
//set viewModels to fragment activity
1832
//and we cast that as MainActivity so that we can have access to the view model created at MainActivity
1933
viewModel= (activity as MainActivity).viewModel
34+
setupRecyclerView()
35+
36+
//implementing search delay
37+
var job: Job? = null
38+
etSearch.addTextChangedListener {editable->
39+
job?.cancel() //cancel current job
40+
41+
//new job
42+
job= MainScope().launch {
43+
delay(SEARCH_DELAY)
44+
45+
//after delay, check editable for null,
46+
editable?.let {
47+
if (editable.toString().isNotEmpty()){
48+
viewModel.searchNews(editable.toString())
49+
}
50+
}
51+
}
52+
}
53+
54+
//subscribe to live data
55+
viewModel.searchNews.observe(viewLifecycleOwner, Observer { response->
56+
when(response){
57+
is Resource.Success->{
58+
hideProgressBar()
59+
//check null
60+
response.data?.let { newsResponse ->
61+
newsAdapter.differ.submitList(newsResponse.articles)
62+
}
63+
}
64+
is Resource.Error->{
65+
hideProgressBar()
66+
response.message?.let { message->
67+
Log.e(TAG, "An error occured: $message" )
68+
}
69+
}
70+
is Resource.Loading->{
71+
showProgressBar()
72+
}
73+
}
74+
})
75+
}
76+
77+
private fun setupRecyclerView(){
78+
newsAdapter= NewsAdapter()
79+
rvSearchNews.apply {
80+
adapter = newsAdapter
81+
layoutManager = LinearLayoutManager(activity)
82+
}
83+
}
84+
private fun hideProgressBar(){
85+
paginationProgressBar.visibility= View.INVISIBLE
86+
}
87+
private fun showProgressBar(){
88+
paginationProgressBar.visibility= View.VISIBLE
2089
}
2190
}

app/src/main/java/com/sijanneupane/mvvmnews/utils/Constants.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ class Constants {
44
companion object{
55
const val API_KEY= "a7ebed0b55b041e7a20fc6ef542c5322"
66
const val BASE_URL= "https://newsapi.org"
7+
const val SEARCH_DELAY= 500L
78
}
89
}

0 commit comments

Comments
 (0)