简体   繁体   中英

Null when passing data to ViewModel

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

  1. Creating own method to pass data to ViewModel
  2. Using intent to pass data to ViewModel
  3. Defining default value inside ViewModel which works, but can't change after defined

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM