I couldn't inherit RecyclerView.Adapter<something.ViewHolder>() - kotlin

I had trouble inheriting RecyclerView to the class.
the problem occurs from ViewHolder. I already imported RecyclerView
but ViewHolder did not seem to work for me
the code below:
package love.partner.recyclerviewdemo.adapters
import androidx.recyclerview.widget.RecyclerView
class CustomAdapter(private val mList: List<ItemsViewModel>): RecyclerView.Adapter<CustomAdapter.ViewHolder>(){
}

Related

How to solve error with View Binding in Kotlin

Here I'm getting this error
package lk.ac.kln.mit.stu.mobileapplicationdevelopment.activities
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View.inflate
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import lk.ac.kln.mit.stu.mobileapplicationdevelopment.R
class ShoppingActivity : AppCompatActivity() {
val binding by lazy{
ActivityShoppingBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_shopping)
setContentView(binding.root)
val navController = findNavController(R.id.shoppingHostFragment)
binding.bottomNavigation.setupWithNavContoller(navController)
}
}
Anyone know the reason to fail this code?
I tried adding below lines to the gradel as well
buildFeatures {
viewBinding true
}
You can better use this, this way the binding can be set in the onCreate as before this it can not build UI components.
var binding: ActivityShoppingBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
binding = ActivityShoppingBinding.inflate(layoutInflater)
binding?.let {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_shopping)
setContentView(binding.root)
val navController = findNavController(R.id.shoppingHostFragment)
binding.bottomNavigation.setupWithNavContoller(navController)
}
}
ActivityShoppingBinding is in red because it's not recognised by the IDE - usually this means you haven't imported it, so it doesn't know what it is. And you don't have an import line for that class, so that's probably your problem!
The easiest fix is just to put your cursor over the error and do Alt+Enter (or whatever) or click the lightbulb icon that appears, and the IDE will offer to import it for you. Once that binding class is imported it should work fine.
Also you're calling setContentView twice - that's pointless (you're inflating a layout then throwing it away immediately) and it can introduce bugs if you accidentally set things on a layout that isn't being displayed. You should only be calling it once, with binding.root in this case.
You might want to look at the recommended way of initialising view binding in Activities (and the Fragments section too if you're using them). Avoid using lazy for UI stuff, since it can only be assigned once you can run into issues (mostly with Fragments, but the example in that link uses lateinit too)

Merging Activities in kotlin

I have three different activities which extends three different things and i want to implement multi level inheritance so that i can add it in android:name of androidmanifest.
Here are all activities. I don't know native development at all. Any help would be appreciated.
1st activity
package com.package
import hrx.plugin.monet.MonetApplication
class CustomApplication : MonetApplication()
2nd activity
package com.package
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
3rd activity
package com.package;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.androidalarmmanager.AlarmService;
class Application : FlutterApplication(), PluginRegistrantCallback {
override fun onCreate() {
super.onCreate();
AlarmService.setPluginRegistrant(this);
}
override fun registerWith(registry: PluginRegistry) {
GeneratedPluginRegistrant.registerWith(registry);
}
}
I have three different activities
Actually, you seem to have two different Application objects and one Activity. If you don't know the difference you may want to go back and take some Android 101 courses.
i want to implement multi level inheritance so that i can add it in android:name of androidmanifest.
OK. Well you have
class CustomApplication : MonetApplication()
and
class Application : FlutterApplication(), PluginRegistrantCallback
Looking at the definition of MonetApplication we see that it's defined as
open class MonetApplication : FlutterApplication()
So MonetApplication is a FlutterApplication so if you extend MonetApplication you are effectively also extending FlutterApplication, so you can basically merge your two existing classes into one:
class HighlanderApplication : MonetApplication(), PluginRegistrantCallback {
override fun onCreate() {
super.onCreate();
AlarmService.setPluginRegistrant(this);
}
override fun registerWith(registry: PluginRegistry) {
GeneratedPluginRegistrant.registerWith(registry);
}
}
Now you can use HighlanderApplication in your manifest and get all the logic that was in both.

Dagger2 generate multiple instances

I'm using Dagge2 in my kotlin project with pom file. I worked with Dagger in my android projects and it worked fine. But somehow I don't understand why Dagger generating multiple instances of my every object in kotlin.
Below is my Component
#Singleton
#Component(modules = [MeterCollectionModule::class])
interface AppComponent {
fun meterCollection(): MeterCollection
}
And this is my Module
#Module(includes = [UtilModule::class])
class MeterCollectionModule {
#Singleton
#Provides
fun meterCollection() = MeterCollection()
}
That's how I'm building my AppComponent
DaggerAppComponent
.builder()
.build()
.inject(this)
I debug my code and see, every time I inject MeterCollection class it gives me new object.
The #Singleton annotation (as well as any other scope annotation) is taken into account only if you're reusing the same component. In other words, Dagger is not able to respect your #Singleton scope across different instances of the same component.
Hence, in order to inject the same MeterCollection instance, you should also reuse the same DaggerAppComponent instance (e.g., by putting it in an instance variable).
Singleton and Provider annotations won't work with object which is created every time method is called. I'd refactor the class to:
#Module(includes = [UtilModule::class])
class MeterCollectionModule {
val myMeterConnection = MeterConnection()
#Singleton
#Provides
fun meterCollection(){
return myMeterConnection
}
(which is identical solution to what #user2340612 proposed)

How should an inline function on a Kotlin class be imported

There is a kotlin file in a project dependency jar (called, for example, KotlinClass) with an inline function
package io.pack
inline fun <T> every(){
///does stuff
}
If I import it into a Java class as a static:
import static io.pack.KotlinClass.every;
The import is recognised.
If I import it into a Kotlin class:
import io.pack.every
or (this ought not to work anyway, but tried for completeness) as
import io.pack.KotlinClass.every
It is not recognised.
(Note: If I create my own Kotlin file with an inline function, then that can be imported into a Kotlin class with no problem. The problem is when importing from a specific project dependency.)
What might be stopping the import of this function into a kotlin class?
It works for me. I create a Kotlin module with a file called TopLevelStandalone.kt:
package io.pack
inline fun every(){
print("Inline")
}
fun normalFun() {
print("Normal")
}
The jar this project builds into contains the class file, and a META-INF/top-level-standalone.kotlin_module containing:
io.packTopLevelStandaloneKt
I then create another Kotline module, manually adding the jar to its dependencies. I'm now able to call every or normalFun:
import io.pack.every
import io.pack.normalFun
fun main(args: Array<String>) {
every()
normalFun()
}

Exception when using spring-data-mongodb with Kotlin

I'm new to Kotlin, and experimenting with spring-data-mongodb. Please see example below (also available here as fully runnable Maven project with in-memory MongoDb: https://github.com/danielsindahl/spring-boot-kotlin-example).
Application.kt
package dsitest
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
#SpringBootApplication
open class Application
fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
User.kt
package dsitest
import org.springframework.data.annotation.Id
import org.springframework.data.annotation.PersistenceConstructor
import org.springframework.data.mongodb.core.mapping.Document
#Document(collection = "user")
data class User #PersistenceConstructor constructor(#Id val id: String? = null, val userName: String)
UserRepository.kt
package dsitest
import org.springframework.data.repository.CrudRepository
interface UserRepository : CrudRepository<User, String>
KotlinIntegrationTest.kt
package dsitest
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner
#RunWith(SpringRunner::class)
#SpringBootTest
class KotlinIntegrationTest constructor () {
#Autowired
lateinit var userRepository : UserRepository;
#Test
fun persistenceTest() {
val user : User = User(userName = "Mary")
val savedUser = userRepository.save(user)
val loadedUser = userRepository.findOne(savedUser.id) // Failing code
println("loadedUser = ${loadedUser}")
}
}
When running the test KotlinIntegrationTest.persistenceTest, I get the following error message when trying to retrieve a User object from MongoDb:
org.springframework.data.mapping.model.MappingException: No property null found on entity class dsitest.User to bind constructor parameter to!
If I modify the User data class so that userName is nullable, everything works.
data class User #PersistenceConstructor constructor(#Id val id: String? = null,
val userName: String? = null)
I would like to understand why this is the case, since I don't want userName to be nullable. Is there some alternative, better way of defining my User class in Kotlin?
Many thanks,
Daniel
Yes, it is a known problem. You should check how the bytecode for your User class looks like. Java sees the constructor with all the parameters present and tries to call it with a null value for the 2nd one.
What you could do is to try adding #JvmOverloads to your constructor - this will force Kotlin compiler to generate all versions of the constructor and so the Spring Data Mongo could pick the correct one (get rid of the #PersistenceConstructor) then.
You could also define 1 constructor with no defaults - only for Java-based frameworks and 2nd one with some defaults your you. Or...
When I write things like you are now, I create simple 'persistence' data classes with no default values whatsoever that are mapped to/from my regular domain objects (a sort of abstraction over database). It may generate some overhead at the start - but keeping your domain model not coupled so tightly with the storage model is usually a good idea anyway.