I have a "insert_data()" function in same class with RecyleView's adapter class. With this method, I'll populate an array.
That method works after clicking an "setOnClickListener".
So onBindViewHolder method's codes are below,
override fun onBindViewHolder(holder: adsViewHolder, position: Int) {
holder.itemView.txt_ads.text = category[position]
holder.itemView.setOnClickListener(){
if (holder.itemView.txt_ads.text.contains("Estate")){
var arrayID = holder.itemView.resources.getIdentifier("EstateCategory","array", holder.itemView.context.packageName )
var category_arraylist = ArrayList<String>(9)
i**nsert_data(category_arraylist,arrayID)**
var mylinearlayout = LinearLayoutManager(holder.itemView.context,LinearLayoutManager.VERTICAL, false)
holder.itemView.myAdsRecycleView.layoutManager = mylinearlayout
var myadapter = adsRecyleAdapter(category_arraylist)
holder.itemView.myAdsRecycleView.adapter = myadapter
}
}
}
and "insert_data()" method's codes are below,
fun insert_data(categoryArraylist: ArrayList<String>,arrayID:Int) {
var obje = AppCompatActivity()
var Category = obje.resources.getStringArray(R.array.EstateCategory)
for (i in 0..obje.resources.getStringArray(R.array.realEstateCategory).size -1 ){
categoryArraylist.add(Category[i])
}
}
Wtihin this method, I cant reach "resources". To solve this, I created and object from AppCombatActivity class. But it gives error like below at "var obje = AppCompatActivity()" line.
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
How can I reach resources with this method? "this", or "context" doesn't works.
Pass in the itemView into the insertData method and call the resources the same way you're calling them in other places
insertData(itemView: View) {// along with your other parameters
itemView.resources.getStringArray(..)
}
Related
class MainAcitvity
fun roomSetup(){
setFavouriteDao = FavouriteDatabase.getDatabase(applicationContext).setFavouriteDao()
repositoryRoom = LorRepository(setFavouriteDao)
viewModelRoom = ViewModelProvider(this,LorViewModelFactory(repositoryRoom!!)).get(LorViewModel::class.java)
}
override fun onMovieClick(position: Int) {
roomSetup()
Toast.makeText(this#MainActivity, "clicked!"+position, Toast.LENGTH_SHORT).show()
var setFavourite = SetFavourite(movieResponse!!.docs[position].Id.toString(),movieResponse!!.docs[position].name.toString())
viewModelRoom.addToFavourites(setFavourite)
}
class ViewModel
fun addToFavourites(setFavourite: SetFavourite){
viewModelScope.launch(Dispatchers.IO){
lorRepository.addToFavourites(setFavourite)
}
}
class LorRepository( favouriteDao: SetFavouriteDao?) {
var favouriteDao : SetFavouriteDao
init {
this.favouriteDao = favouriteDao!!
}
private var lorApi: LORApi.LorCalls? = null
constructor(lorApi2 : LORApi.LorCalls?, favouriteDao: SetFavouriteDao?) : this(favouriteDao){
this.lorApi = lorApi2
}
I have 2 constructors
one to initialize room other for initializing retrofit
I am Also doubtful about the constructor in Repository. Thoose are made for 2 different purposes, one for initializing room database and other for repository. but everytime I create one object of room/retrofit the second constructor , when called, fills it with null values
My questions for you are:
Why do you to initialize retrofit and room's dao in a separate constructor?
What is it that you try to achieve?
In your code you only call to initialize dao constructor, therefore lorApi is null.
For your case you wouldn't want to initialize them separately.
Change your code to this:
class LorRepository(private val lorApi : LORApi.LorCalls, private val favouriteDao: SetFavouriteDao)
I'm learning/using RecyclerViews and while my app works (at the moment!), there are two things that I don't understand.
Here are my ViewHolder declarations:
class AAAViewHolder ( view: View, var aaa: AAA? = null) : RecyclerView.ViewHolder (view) {...}
class BBBViewHolder (val view: View, var bbb: BBB? = null) : RecyclerView.ViewHolder (view) {...}
class CCCViewHolder ( view: View, var ccc: CCC? = null) : RecyclerView.ViewHolder (view) {...}
Why does BBBViewHolder have the extra val? If I remove it, then I get an "Unresolved reference: view" compiler error in onBindViewHolder in the ViewAdapter class. Why? And, if I *add the val declaration to AAA and CCC, Android Studio tells me that it's not needed and offers to remove it for me.
Next, there's something odd about the onBindViewHolder functions.
AAAListAdapter.kt (not showing getItemCount or onCreateViewHolder):
class AAAListAdapter : RecyclerView.Adapter<AAAViewHolder>() {
override fun onBindViewHolder(holder: AAAViewHolder, position: Int) {
val aaa = aaaList[position]
holder.itemView.aTextView.text = "AAA"
holder.aaa = aaa
}
}
BBBListAdapter.kt
class BBBListAdapter : RecyclerView.Adapter<BBBViewHolder>() {
override fun onBindViewHolder(holder: BBBViewHolder, position: Int) {
val bbb = bbbList[position]
holder.view.bTextView.text = "BBB"
holder.bbb = bbb
}
}
CCCListAdapter.kt
class CCCListAdapter : RecyclerView.Adapter<CCCViewHolder>() {
override fun onBindViewHolder(holder: CCCViewHolder, position: Int) {
val ccc = cccList[position]
holder.itemView.cTextView.text = "CCC"
holder.ccc = ccc
}
}
The code is almost identical, except why does BBBListAdapter reference holder.view, while the other two reference holder.itemView? Where are those properties declared? Can I control that? I'd much prefer them to be the same.
Seeing how A & C act the same but B is different, I'm guessing the two questions are related, but I don't know.
Firstly you declare val/var inside constructor to use those values somewhere in class without declaring or intializing it anywhere in your class. Let take in example, i want a list in adapter I'll pass it in adapter and in adapter I won't use val/var then and I can't use that unless I create a variable before hand and initialise it inside its default constructor.
class A() {
lateinit var view : View
constructor(view : View) {
this.view = view
}
view.textView.text = "Redundant Code"
}
Now you could have reduced this just by declaring it inside constructor itself.
class A(val view : View) {
view.textView.text = "Easy way"
}
Now coming to your use case, viewholder A and C are identical, and B has view is declared and you are using it, but from the code in adapter I don't think it is necessary, the same logic could have been used in Adapter B, holder.itemView.something, holder.itemView is ultimately is the view object which you're using in A and C, so val view is not need for that particular case.
If you're using it somewhere, then add the whole code, there I might be able to help you out why ViewHolder B is different. But from what you have posted, there is no need for using val inside constructor.
I am trying to develop a Notes application where I can save list of notes. These notes will be saved in SQLite DataBase. I have set a button to delete the created note. When I click on this butting during run time (no complete time error) it is giving me a mentioned error. Kindly help in resolving this issue.
I tried to develop this app by reading and copying the code from
https://github.com/hussien89aa/KotlinUdemy/tree/master/Android/NoteApp/StartUp
inner class MyNotesAdapter : BaseAdapter {
var listNotesAdapter = ArrayList<note>()
var context: Context? = null
constructor(listNotesAdapter: ArrayList<note>) : super() {
this.listNotesAdapter = listNotesAdapter
this.context = context
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
var myView = layoutInflater.inflate(R.layout.ticket, null)
var myNote = listNotesAdapter[position]
myView.tvTitle.text = myNote.nodeName
myView.tvDes.text = myNote.nodeDes
myView.delete.setOnClickListener(View.OnClickListener {
var dbManager = DbManager(this.context!!) //This is the line where I am getting error.
val selectionArgs = arrayOf(myNote.nodeID.toString())
dbManager.Delete("ID=?", selectionArgs)
LoadQuery("%")
})
You're getting a KotlinNullPointerException here because of the failed null assertion in the expression context!! in that line: !! operator ensures that the expression to the left is not null or throws KNPE otherwise.
Here context variable is null by the time it has been accessed in the OnClickListener. By why is it null? I suppose because it was never assigned to something other than null in this code example. In particular, the following part of code looks suspicious:
inner class MyNotesAdapter : BaseAdapter {
...
var context: Context? = null
constructor(listNotesAdapter: ArrayList<note>) : super() {
...
this.context = context
}
Here you assign the value of context to the context variable, but where does that value come from? The closest identifier with this name is the same context variable, which is initially null, so this variable gets null assigned once again.
In fact, IDE even reports Variable 'context' is assigned to itself warning on this line.
I have create array of color like this in kotlin
private var colorArray = arrayOf(
ContextCompat.getColor(this, R.color.text_yellow),
ContextCompat.getColor(this, R.color.text_green),
ContextCompat.getColor(this, R.color.text_red)
)
and when i want to get color from colorArray through index
var color = colorArray[0]
I am getting crash on index 0,
Attempt to invoke virtual method 'android.content.res.Resources
android.content.Context.getResources()' on a null object reference
I don't know where i am wrong
If i write ContextCompat.getColor(this, R.color.text_yellow) this is fine no crash but through array index it give me error
You're declaring this as a field:
private var colorArray = arrayOf(
ContextCompat.getColor(this, R.color.text_yellow),
ContextCompat.getColor(this, R.color.text_green),
ContextCompat.getColor(this, R.color.text_red)
)
The issue is that your context (the this parameter) is null before your onCreate() method is called. And when you declare something as a field, it tries to initialise it immediately, before any method calls. (So before the onCreate is called)
What you can do is initialise this field with a lazy call.
This means that it is actually only initialised when it is first used. So if you're calling the index AFTER your onCreate, the context won't be null and it should work fine.
Change it to:
private var colorArray by lazy { arrayOf(
ContextCompat.getColor(this, R.color.text_yellow),
ContextCompat.getColor(this, R.color.text_green),
ContextCompat.getColor(this, R.color.text_red)
) }
You are using this as Context globally which is not initialized yet .
This is why you are getting this error cause Context is null.
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()
The Right way to do this access the context inside onCreate(). You can try something like below:-
class Dx :AppCompatActivity(){
private lateinit var colorArray:Array<Int>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dx)
colorArray = arrayOf(
ContextCompat.getColor(this, R.color.colorAccent),
ContextCompat.getColor(this, R.color.colorPrimary),
ContextCompat.getColor(this, R.color.colorPrimaryDark)
)
val btn=findViewById<Button>(R.id.b1)
btn.setBackgroundColor(colorArray[0])
}
}
I'm working in a Android project using Kotlin. I have this piece of code:
val foo = FooClass(this)
var colorRunning = FooClass.getProperty("myproperty")
and the class FooClass is:
class FooClass(val context: Context) : SomeHeritance{
private val styles: HashMap<String, String> = hashMapOf()
override fun onCreate(context: Context?) {
Log.e("Hash is empty here", this.styles.size.toString())
this.styles.put("a","a")
this.styles.put("b","a")
this.styles.put("c","a")
Log.e("Hash is size is 3", this.styles.size.toString())
}
override fun getProperty(someProp: String) {
Log.e("Hash is size is 0", this.styles.size.toString()) //I don't understand why
return styles[someProp]!!
}
The problem is that the HashMap styles get initialized in the onCreate method, but when I want to access to some of the values there from the method getPropery the HashMap is empty.
Making some tests, I could check that if I initialize the HashMap on the method getProperty the hash remains initialized.
Seems like your onCreate is not called on start. Put the init of your Map inside an init block:
init {
with(styles){
put("a","a")
put("b","a")
put("c","a")
}
}
That way you can be sure to have the values put into the map before accessing it.
Also make sure to hande null values in your getProperty correctly. Instead of !! you could throw an Exception:
fun getProperty(someProp: String): String
= styles[someProp] ?: throw IllegalArgumentException()