Im using this kotlin Room project and trying to instantiate "viewModel" that needs a Dao parameter
https://github.com/googlesamples/android-architecture-components/tree/master/BasicRxJavaSampleKotlin/app/src/main/java/com/example/android/observability
the project uses this line to to it:
private val viewModel: UserViewModel by viewModels()
but i cant get viewModels() to resolve.
i noticed the project has this import
import androidx.activity.viewModels
but "activity" is red and not resolving.
i have another viewmodel B with no parameter that is instantiated by
val model = ViewModelProviders.of(this)[MyViewModel::class.java]
i am trying to figure out why the import is red for me
also is it possible to instantiate a viewmodel with parameters in the second way of instantiating?
please let me know if i need to include other files to determine.
Related
I'm learning dependency injection by the article.
I'm very confused between "Inject dependencies into Android classes" and "Generated components for Android classes" ? What are different?
For example:
Code A has generated components for Android classes with #InstallIn(ActivityComponent::class), should Code B still add the annotation #AndroidEntryPoint?
Code A
#Module
#InstallIn(ActivityComponent::class)
object AnalyticsModule {
#Provides
fun provideAnalyticsService(
#AuthInterceptorOkHttpClient okHttpClient: OkHttpClient
): AnalyticsService {
return Retrofit.Builder()
.baseUrl("https://example.com")
.client(okHttpClient)
.build()
.create(AnalyticsService::class.java)
}
}
Code B
#AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {
#Inject lateinit var mAnalyticsService: AnalyticsService
...
}
Added Content
If I havn't any #Module in my project and add only such as #AndroidEntryPoint before Acitiviy, Hilt automagically creates predetermined Component for me, is it right?
If I have some #Module such as AnalyticsModule in my project and add such as #AndroidEntryPoint before Acitiviy, Hilt automagically creates predetermined Component and my dependency injection provideAnalyticsService for me, is it right?
Inject dependencies into Android classes
This means, that you can inject dependencies (such as AnalyticsService) into android classes (such as Activities, Application or fragments), that are either annotated with #HiltAndroidApp or #AndroidEntryPoint.
If you annotate a fragment or activity with #AndroidEntryPoint, Hilt automagically creates a HiltComponent for this class (the same you do with #Module #InstallIn etc.. just in the background).
The Developers just want to tell you, that you CAN inject something into an android class, BUT you have to annotate them before doing that:
Application (by using #HiltAndroidApp)
ViewModel (by using #HiltViewModel)
Acitiviy (by using #AndroidEntryPoint)
Fragment (by using #AndroidEntryPoint)
etc
Generated components for Android classes
These are the components, that Hilt provides to YOU in order to inject something to it's corresponding class. For example, if you want to provide a dependency to the entire application (every class can access this dependency), than you would use a SingletonComponent. But if you want to provide let's say a dependency only to a viewmodel (no other class should have access to it), that you would install this dependency inside a ViewModelComponent
Edit
If I havn't any #Module in my project and add only such as #AndroidEntryPoint before Acitiviy, Hilt automagically creates predetermined Component for me, is it right?
Yes that is correct, but it only creates such components that hilt need in order to provide any dependency to an activity.
If I have some #Module such as AnalyticsModule in my project and add
such as #AndroidEntryPoint before Acitiviy, Hilt automagically creates
predetermined Component and my dependency injection
provideAnalyticsService for me, is it right?
Yes that is sorta right: With #AndroidEntryPoint hilt makes sure, that every dependency that you provide via #Module #InstallIn(...) can be injected inside a android class. You should not forget the following: Android is a framework and you as a user never create such classes like Activity or Fragment (you write code in it, but don't create them, the framework does this for you). With this in mind, you as a user have to annotate Android-Classes with #AndroidEntryPoint in order to tell hilt, that it should create it's corresponding modules so that you can inject dependencies inside a android-class.
I have a
data class A(){
fun c(){}
} .
I need to create a fake implementation of it for testing, but it says that class must be open. open modifier is incompatible with data class. Any ways to do it?
To mock final classes update mockito
testCompile 'org.mockito:mockito-core:2.8.9'
and then add a folder in your resources folder called mockito-extensions that includes a text file called org.mockito.plugins.MockMaker. Inside there just add
mock-maker-inline
That should solve your problem
In my IntelliJ IDEA project, I have 3 modules written in Kotlin:
An HTTP Servlet one.
A desktop swing application; and
A library that contains contracts that the above two listed projects share to talk to each other.
When I click the Run button, it starts the Tomcat server and loads up my servlet project. That is because, and I am guessing here, the new project creation template inside of the IDE created a new Run Configuration for the entire project and it is defined in this run configuration that it must start the module that has the servlet inside it.
Now that the servlet runs fine, I'd like to also run the desktop application written using Swing.
How do I do that? I've done this once before but I have forgotten how I did it.
Do I have to define a new Run Configuation? I tried that this way:
I selected Kotlin from the left pane titled Add New Configuration and specified the name of the class that had the main function, and also the name of the module that had this class.
Here is the source code of my main class.
package bookyard.client;
import javax.swing.SwingUtilities;
public class Program {
public fun main(args : Array<String>) {
SwingUtilities.invokeLater(LoginDialogEventLoop());
}
}
But when I click the Run button after choosing that run configuration's name, the process reports an error that suggests that the class name I specified as having the main function actually does not have the main function, which I am not sure why that is.
The main method needs to be static, and the method you have declared is not. In Kotlin, you can either declare main as a top-level function (outside of a class), or, if you want to keep it inside the class, use the following syntax:
class Program {
companion object {
#JvmStatic fun main(args: Array<String) { ... }
}
}
I am new in kotlin. I have found and tried to use synthetic method instead of annoying method findViewById in my Activity class, but I have found "If we want to call the synthetic properties on View (useful in adapter classes), we should also import kotlinx.android.synthetic.main.view.*." But I can't figure out how it exactly works? Is there any examples?
Simple example from https://github.com/antoniolg/Kotlin-for-Android-Developers
import kotlinx.android.synthetic.item_forecast.view.*
class ForecastListAdapter() : RecyclerView.Adapter<ForecastListAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindForecast(forecast: Forecast) {
itemView.date.text = forecast.date.toDateString()
}
}
}
No need to write
val view = itemView.findViewById(R.id.date) as TextView
view.text = forecast.date.toDateString()
Just
itemView.date.text = forecast.date.toDateString()
Simple and effective!
Kotling 1.1.4 out
Further information : https://antonioleiva.com/kotlin-android-extensions/
You need to enable Kotlin Android Extentions by adding this to your build.gradle:
apply plugin: 'org.jetbrains.kotlin.android.extensions'
androidExtensions {
experimental = true
}
Since this new version of Kotlin, the Android Extensions have incorporated some new interesting features: caches in any class (which interestingly includes ViewHolder)
Using it on a ViewHolder (or any custom class). Note that this class should implement LayoutContainer interface:
class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),
LayoutContainer {
fun bind(title: String) {
itemTitle.text = "Hello Kotlin!"
}
}
You need
import kotlinx.android.synthetic.row_wall.view.*
And later something along the lines of:
convertView.titleText.text = item.title
The point is that the view.* introduces extensions to the View class.
Try
class CustomViewModel(val baseView: View) {
val firstName = baseView.firstName
val lastName = baseView.lastName
}
View object exposes the views
ref:https://discuss.kotlinlang.org/t/unable-to-use-kotlin-android-extension-in-adapter-class/2890
If you are using the latest version l;.you don't have to add experimental = true to it.
in Project level Gradle
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.21'
And in app level Gradle
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' //These should be on the top of file.
and in dependencies..
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21'
and import below as
import kotlinx.android.synthetic.main.your_layout_file_name.view.*
and example
import kotlinx.android.synthetic.main.item_animal.view.*
class AnimalVH(parent: ViewGroup, layoutID: Int) : BaseViewHolder<Animal>(parent, layoutID) {
override fun bindData(animal: Animal) {
itemView.tv_animal.text = animal.title
}
}
where BaseViewHolder is
abstract class BaseViewHolder<T>(parent: ViewGroup, layoutID: Int) : RecyclerView.ViewHolder(
LayoutInflater.from(parent.context).inflate(layoutID, parent, false)
) {
abstract fun bindData(model: T)
}
It means you have to place this line at the beginning of your source file:
import kotlinx.android.synthetic.main.view.*
So now instead of, for example, findView(R.id.textView) as TextView you would write just textView. The latter is a synthetic extension property located in the package kotlinx.android.synthetic.main.view, that's why you have to import everything from it.
There's a tutorial on the official site, take a look.
FYI: Data binding is recommended over synthetic for view lookups.
Comment from a DA for Android from Google on Reddit
Hey! Developer Advocate for Android at Google here!
I wanted to add a bit of background here. Kotlin Extensions with
synthetic views was never intentionally “recommended” though that
shouldn’t be taken as a recommendation to not use them. If they're
working for you please feel free to continue using them in your app!
We’ve been shifting away from them (e.g. we don’t teach them in the
Udacity course) because they expose a global namespace of ids that’s
unrelated to the layout that’s actually inflated with no checks
against invalid lookups, are Kotlin only, and don't expose nullability
when views are only present in some configuration. All together, these
issues cause the API to increase number of crashes for Android apps.
On the other hand, they do offer a lightweight API that can help
simplify view lookups. In this space it's also worth taking a look at
Data Binding which also does automatic view lookups - as well as
integrates with LiveData to automatically update your views as data
changes.
Today, there's a few options in this space that work:
Data Binding is the recommendation for view lookup as well as binding,
but it does add a bit of overhead when compared to Android Kotlin
Extensions. It's worth taking a look to see if this is a good fit for
your app. Data Binding also allows you to observe LiveData to bind
views automatically when data changes. Compared to Kotlin Extensions,
it adds compile time checking of view lookups and type safety. Android
Kotlin Extensions is not officially recommended (which is not the same
as recommendation against). It does come with the issues mentioned
above, so for our code we're not using them. Butter Knife is another
solution that is extremely popular and works for both Kotlin and the
Java Programming Language. Reading through the comments here there's a
lot of developers that are having great luck with Kotlin Extensions.
That's great - and something we'll keep in mind as we look at ways to
continue improving our APIs. If you haven't taken a look at Data
Binding, definitely give it a shot.
As an aside, our internal code style guide is not intended to be
directly applied outside of our codebase. For example, we use
mPrefixVariables, but there's no reason that every app should follow
that style.
Hi I am quite new to actionscript 3 and I would like some clarification on the use of classes. I am trying to use a AS3Commons UI project from http://sibirjak.com. But I am unsure on how to use some of their classes. The way I have it formatted in one of my keyframes is:
import com.AlertBox; // The location of the alertbox class
import com.AlertTutorialStep1; // The location of the example AlertTutorialStep1 class
var alertbox:AlertTutorialStep1 = new com.AlertTutorialStep1; // Creating an instance of the example class in the AlertTutorialStep1 doc
alertbox.AlertTutorialStep1(); // Trying to access the AlertTutorialStep1() function which is in the AlertTutorialStep1 class
But I am unable to access the function AlertTutorialStep1() and unsure why I am getting the error, can someone provide me with some insight? http://sibirjak.com/osflash/blog/tutorial-creating-an-alert-box-with-the-as3commons-popupmanager/
Try and avoid using the timeline if possible. I think that OOP and the Flash timeline can work if you know what you're doing, but stackoverflow is full of questions from beginners struggling with the timeline and classes, and these tend to be difficult to debug. Try to set your project up with a single Main document class which instantiates all the other classes you need for your project.
That said, assuming you have the AlertBox and AlertTutorialStep1 classes, and their dependencies, in the right directories relative to it, I think your code will work if you set the document class of your .fla to the AlertBoxTutorial1 class.
Again assuming the packages are all set up correctly, you could try replacing your existing code with the following:
//import com.AlertBox; // Don't need to import this, AlertTutorialStep1 imports and uses it
import com.AlertTutorialStep1; // The location of the example AlertTutorialStep1 class
var alertbox:AlertTutorialStep1 = new AlertTutorialStep1(); // Don't need to fully qualify the class as it is already imported in the line above
this.addChild(alertbox); // Need to add the instance to the stage
//alertbox.AlertTutorialStep1(); // AlertTutorialStep1() is the constructor of the class and can't be invoked via an instance of it