Reputation: 250
I do not have very much experience with Kotlin, been doing most of my development in Java. I have converted my ArtistFragment to Kotlin in order to solve another issue. But after converting it I am getting to errors that I do not know how to resolve.
The first one is Smart cast to 'RecyclerView!' is impossible, because 'recyclerView' is a mutable property that could have been changed by this time and the second one is Cannot create an instance of an abstract class
I searched through Stackoverflow, but since I don't really understand the what the problem is I am not sure if they are relevant to my problems.
Here is my converted ArtistFragment:
class ArtistFragment : Fragment() {
var spanCount = 3 // 2 columns
var spacing = 20 // 20px
var includeEdge = true
private var recyclerView: RecyclerView? = null
private var adapter: ArtistAdapter? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_artist, container, false)
recyclerView = view.findViewById(R.id.artistFragment)
recyclerView.setLayoutManager(GridLayoutManager(activity, 3))
LoadData().execute("")
return view
}
abstract inner class LoadData : AsyncTask<String?, Void?, String>() {
protected fun doInBackground(vararg strings: String): String {
if (activity != null) {
adapter = ArtistAdapter(activity, ArtistLoader().artistList(activity))
}
return "Executed"
}
override fun onPostExecute(s: String) {
recyclerView!!.adapter = adapter
if (activity != null) {
recyclerView!!.addItemDecoration(GridSpacingItemDecoration(spanCount, spacing, includeEdge))
}
}
override fun onPreExecute() {
super.onPreExecute()
}
}
}
I am seeing Smart cast to 'RecyclerView!' is impossible, because 'recyclerView' is a mutable property that could have been changed by this time here in this section: recyclerView.setLayoutManager(GridLayoutManager(activity, 3))
I am seeing Cannot create an instance of an abstract class here in this section LoadData().execute("")
I hoping someone can explain these error and how to fix them.
Thanks
Upvotes: 0
Views: 189
Reputation: 19622
Smart cast to 'RecyclerView!' is impossible, because 'recyclerView' is a mutable property that could have been changed by this time is because recyclerView
is a var
. Kotlin has the concept of mutable (var
) and immutable (val
) variables, where a val
is a fixed value, but a var
can be reassigned.
So the issue is that recyclerView
is a nullable type (RecyclerView?
) and it could be null - so you need to make sure it's not null before you access it, right? findViewById
returns a non-null RecyclerView
, which gets assigned to recyclerView
, so the compiler knows it can't be null.
But then it gets to the next line - what if the value of recyclerView
has changed since the previous line? What if something has modified it, like on another thread? It's a var
so that's possible, and the compiler can't make any guarantees about whether it's null or not anymore. So it can't "smart cast to RecyclerView!
" (!
denotes non-null) and let you just treat it as a non-null type in your code. You have to null check it again.
What Priyanka's code (recyclerView?.setLayoutManager(GridLayoutManager(activity, 3))
) does is null-checks recyclerView
, and only makes the call if it's non-null. Under the hood, it's copying recyclerView
to a temporary val
(which isn't going to change) and checks that, and then executes the call on that.
This is a pretty standard thing with Kotlin, and not just for nullable types - any var
could possibly change at any moment, so it's typical to assign it to a temporary variable so you can do the stuff on that stable instance. Kotlin has a bunch of scope functions which are convenient for doing things on an object, and one of the benefits is that you know the reference you're acting on isn't going to change halfway through
Upvotes: 1
Reputation: 1875
As your recyclerview is a nullable property, You need to modify your code as below -
recyclerView?.setLayoutManager(GridLayoutManager(activity, 3))
Remove abstract from class
inner class LoadData : AsyncTask<String?, Void?, String>()
Upvotes: 1