So I have a ViewModel
that retrieve query for search API. For that, I also have SearchView
but when typing the first letter on SearchView
the app crashed because KotlinNullPointer
on this line inside retrofit
resultsItem?.value = resultsItemList as List<ResultsItem>?
I think I have done everything right, I tried
Here is the code for the Fragment
class Search : Fragment() {
var searchAdapter: SearchAdapter? = null
lateinit var recyclerView: RecyclerView
lateinit var model: picodiploma.dicoding.database.picodiploma.dicoding.database.search.adapter.SearchView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_search, container, false)
recyclerView = view.findViewById(R.id.search_result_tv)
val layoutManager = LinearLayoutManager(context)
recyclerView.layoutManager = layoutManager
model = ViewModelProviders.of(this).get(picodiploma.dicoding.database.picodiploma.dicoding.database.search.adapter.SearchView::class.java)
return view
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.search, menu)
val searchItem = menu.findItem(R.id.search_)
val searchView = searchItem?.actionView as SearchView
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(s: String): Boolean {
return false
}
override fun onQueryTextChange(s: String): Boolean {
model.query = s
getViewData()
return true
}
})
}
fun getViewData() {
model.getData().observe(this, Observer { resultsItem ->
searchAdapter = SearchAdapter((resultsItem as ArrayList<ResultsItem>?)!!, this.context!!)
recyclerView.adapter = searchAdapter
recyclerView.visibility = View.VISIBLE
})
}
}
And the ViewModel
class SearchView : ViewModel() {
private val API_KEY = "2e08750083b7e21e96e915011d3f8e2d"
private val TAG = SearchView::class.java.simpleName
lateinit var query: String
companion object {
var resultsItem: MutableLiveData<List<ResultsItem>>? = null
}
fun getData(): LiveData<List<ResultsItem>> {
if (resultsItem == null) {
resultsItem = MutableLiveData()
loadData()
}
return resultsItem as MutableLiveData<List<ResultsItem>>
}
private fun loadData() {
val apiInterface = ApiClient.getList().create(ApiInterface::class.java)
val responseCall = apiInterface.getTvSearch(API_KEY, query)
responseCall.enqueue(object : Callback<Response> {
override fun onResponse(call: Call<Response>, response: retrofit2.Response<Response>) {
val resultsItemList = response.body()!!.results
resultsItem?.value = resultsItemList as List<ResultsItem>?
}
override fun onFailure(call: Call<Response>, t: Throwable) {
Log.d(TAG, t.toString())
}
})
}
}
What am I doing wrong?
Change below line
var resultsItem: MutableLiveData<List<ResultsItem>>? = null
to
var resultsItem: MutableLiveData<List<ResultsItem>>? = MutableLiveData()
Put everything inside apply
run{
searchAdapter = SearchAdapter((resultsItem as ArrayList<ResultsItem>?)!!, this.context!!)
recyclerView.adapter = searchAdapter
recyclerView.visibility = View.VISIBLE
}
Seems like you defined resultsItem
as nullable MutableLiveData
, but the List<ResultsItem>
inside your LiveData is not nullable. So I guess your resultsItemList
is null when you get response from the server. And you are getting KotlinNullPointer
because you are trying to assign null
to notNull value of resultsItem
LiveData.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.