I am using mvvm architecture and injecting the repository in the viewmodel using hilt. There is a variable in the activity (i am getting the variable in the activity through an intent) which i need to pass to the viewmodel and i thought viewmodel factories might help. But how to use it alongside hilt?
I am not aware of hilt implementing any sort of "assisted injection" for viewmodels, like the assisted injection library from square. But you can easily manage dynamic data within your viewmodel using this sample from this google sample.
fun setLogin(login: String?) {
if (_login.value != login) {
_login.value = login
}
}
with this code you will only update the livedata if the value is null, thus even if the fragment rotates, the data will remain the same.
If you wanna check a slight outdated assisted injection project, I have this one in Kotlin.
Related
I'm learning Clean Architecture with the artical .
I know Domain Layer is the most INNER part of the onion (no dependencies with other layers) and it contains Entities, Use cases & Repository Interfaces.
The following code is from the project https://github.com/lopspower/CleanRxArchitecture
GetListRepo.kt and RepoRepository.kt are located in Domain Layer, you can see Image 1
1: I think the GetListRepo class should be abstract or interface, right?
2: There are three parameters for constructor of the class GetListRepo. I don't understand why the author add dependency injection #Inject for the class's constructor.
I think I can instance GetListRepo with any way in Data Layout, why does the author need to set dependency injection in Domain Layer with Clean Architecture ?
GetListRepo.kt
class GetListRepo
#Inject internal constructor(
private val repoRepository: RepoRepository,
useCaseScheduler: UseCaseScheduler? = null,
logger: Logger? = null
) : SingleUseCase<List<Repo>, String>(useCaseScheduler, logger) {
...
}
RepoRepository.kt
interface RepoRepository {
val isConnected: Boolean
...
}
Image 1
This is similar to your another question about interfaces/abstract classes. I will quote myself:
With such architecture you could create alternative implementations of GetAlbumListUseCase in the future and switch them smoothly. You could even use multiple implementations at the same time, for example different objects use different implementations GetAlbumListUseCase. Note that in your current architecture all objects directly depend on a specific implementation, so switching to another one requires to modify half of your code.
Imagine you did as you suggested, you didn't use dependency injection, but you created GetListRepo object everywhere in your code. Then in the future you need to have two alternative ways of providing the data, e.g. with local files and with remote server. Imagine you need to make it configurable in the application settings. Or imagine that you need to create unit tests and it would be good to provide a fake, testing variant of the GetListRepo.
How would you do this if your code everywhere would just instantiate GetListRepo directly? You would need to modify many different places in the code and put some logic related to loading of application settings, etc. everywhere. By using dependency injection all components receive their dependencies from outside, they don't know how they're being created and you can put your creation logic in one place only.
Making long story short: using DI lets us decouple components of our application. It makes our code more flexible and adaptable to different scenarios.
Background:
I have an annotation processor that builds retrofit interfaces by scanning spring annotations on controllers. I have it set up to work in either kotlin or java based spring applications, and it can generate either kotlin or java retrofit client interfaces.
Question:
When running it against a kotlin based spring application, is there a way to pick up a default value on a controller function, whether reflectively or through some other means?
e.g. the controller function looks something like
#RequestMapping("/foo")
fun getSomething(#RequestParameter foo: String = "bar") {
...
}
and I want to be able to generate a retrofit interface method that looks something like
fun getSomething(#Header foo: String = "bar")
I am aware that the compiler under the hood actually creates multiple override methods for the jvm:
https://discuss.kotlinlang.org/t/retrieve-default-parameter-value-via-reflection/7314
But I'm wondering if there's a way to capture these defaults during the annotation processing phase or if I just have to live without defaults in the generated kotlin client.
Long story short - is there a workaround that would let me capture these defaults?
It would seem that you cannot do that, sadly :( https://discuss.kotlinlang.org/t/kotlin-reflection-and-default-values/2254 the idea is interesting though. I'm not sure if it's desirable to analyze bytecode for this?
It kind of also makes sense because the default value can also come from things like constants, which in turn can be calculated values. If the default param is set through a calculated constant there's no certain way to know what it will be before it's loaded on runtime.
Example:
In #material-ui/core/createMuiTheme.d.ts there are a few interfaces defined, e.g. ThemeOptions and Theme
It's possible to generate koltin bindings using ts2kt and it allows using createMuiTheme function to create Theme from ThemeOptions, but what is a correct [aka type safe] way of instantiating ThemeOptions which is an external interface and it doesn't have a constructor.
I created a data class that implements the interface and instantiate it. Sometimes I need to use the instance as dynamic as it allows 3rd party js code to modify it.
Is this approach any good assuming I don't want to lose type safety and use JsObject/json()/js()?
The described way (implementing an interface by a data class) is good as well as any other way to implement an interface: by usual class, object expression and so on.
You can use jso<ExternalInterface> {}.
Here's an example from the Kotlin wrappers:
https://github.com/karakum-team/kotlin-mui-showcase/blob/main/src/main/kotlin/team/karakum/components/showcases/TextFields.kt
TextField {
asDynamic().InputProps = jso<InputBaseProps> {
startAdornment = InputAdornment.create {
position = InputAdornmentPosition.start
+"kg"
}
}
}
Let's say I have a few controllers. Each controller can at some point create new objects which will need to be stored on the server. For example I can have a RecipeCreationViewController which manages a form. When this form is submitted, a new Recipe object is created and needs to be saved on the server.
What's the best way to design the classes to minimize complexity and coupling while keeping the code as clean and readable as possible?
Singleton
Normally I would create a singleton NetworkAdapter that each controller can access directly in order to save objects.
Example:
[[[NetworkAdapter] sharedAdapter] saveObject:myRecipe];
But I've realized that having classes call singletons on their own makes for coupled code which is hard to debug since the access to the singleton is hidden in the implementation and not obvious from the interface.
Direct Reference
The alternative is to have each controller hold a reference to the NetworkAdapter and have this be passed in by the class that creates the controller.
For example:
[self.networkAdapter saveObject:myRecipe];
Delegation
The other approach that came to mind is delegation. The NetworkAdapter can implement a "RemoteStorageDelegate" protocol and each controller can have a remoteStorageDelegate which it can call methods like saveObject: on. The advantage being that the controllers don't know about the details of a NetworkAdapter, only that the object that implements the protocol knows how to save objects.
For example:
[self.remoteStorageDelegate saveObject:myRecipe];
Direct in Model
Yet another approach would be to have the model handle saving to the network directly. I'm not sure if this is a good idea though.
For example:
[myRecipe save];
What do you think of these? Are there any other patterns that make more sense for this?
I would also stick with Dependency Injection in your case. If you want to read about that you will easily find good articles in the web, e.g. on Wikipedia. There are also links to DI frameworks in Objective C.
Basically, you can use DI if you have two or more components, which must interact but shouldn't know each other directly in code. I'll elaborate your example a bit, but in C#/Java style because I don't know Objective C syntax. Let's say you have
class NetworkAdapter implements NetworkAdapterInterface {
void save(object o) { ... }
}
with the interface
interface NetworkAdapterInterface {
void save(object o);
}
Now you want to call that adapter in a controller like
class Controller {
NetworkAdapterInterface networkAdapter;
Controller() {
}
void setAdapter(NetworkAdapterInterface adapter) {
this.networkAdapter = adapter;
}
void work() {
this.networkAdapter.save(new object());
}
}
Calling the Setter is where now the magic of DI can happen (called Setter Injection; there is also e.g. Constructor Injection). That means that you haven't a single code line where you call the Setter yourself, but let it do the DI framework. Very loose coupled!
Now how does it work? Typically with a common DI framework you can define the actual mappings between components in a central code place or in a XML file. Image you have
<DI>
<component="NetworkAdapterInterface" class="NetworkAdapter" lifecycle="singleton" />
</DI>
This could tell the DI framework to automatically inject a NetworkAdapter in every Setter for NetworkAdapterInterface it finds in your code. In order to do this, it will create the proper object for you first. If it builds a new object for every injection, or only one object for all injections (Singleton), or e.g. one object per Unit of Work (if you use such a pattern), can be configured for each type.
As a sidenote: If you are unit testing your code, you can also use the DI framework to define completely other bindings, suitable for your test szenario. Easy way to inject some mocks!
I want to use Unity as an IoC besides the UnitOfWork and Repository patterns. I read various related articles and questions but none of them satisfied me completely.
I have a problem with all approaches. An example would explain better my problem:
We want to work with two repositories at two separate classes (maybe the business services) but the overall works are in a unit.
Start point is the LocalService1.Method1 method.
public class LocalService1
{
public void Method1(int id)
{
var repository1 = Container.Current.Resolve<IRepository1>(); // Injects the IUnitOfWork for the repository.
var entity1 = repository1.GetEntity1(id);
var service2 = Container.Current.Resolve<LocalService2>(); // Maybe it’s better not to use IoC for business logic. This is not my issue.
service2.Method2(entity1)
}
}
...
public class LocalService2
{
public void Method2(Entity1 entity1)
{
var repository2 = Container.Current.Resolve<IRepository2>(); // Injects the IUnitOfWork for the repository.
var count = repository2.GetEntity2sCount(entity1.Id);
// Do some works with count and entity1
}
}
The main question is that “How can I share the UnitOfWork (here can be ObjectContext) between the IRepository1 and IRepsitory2 while calling the LocalService1.Method1?”.
More important thing is that “I want to be sure about UnitOfWork disposal”.
I guess the answers would focus on these issues:
IoC configuration
Life Time configuration
Disposal time (How and when?)
If you recommend using “HttpContext” please consider about non-web environments.
I know my question is almost about the “Life time management” but I’m looking for an exhaustive approach.
First: Don't use Unity as a ServiceLocator. This is considered an anti-pattern. Use constructor injection instead.
Unity's LifetimeManagers don't clean up after themselves. This feature is on the wish list for Unity vNext.
If you want your objects to be disposed you should create your own LifetimeManager and a related BuilderStrategy that do clean up.
There is a sample in the TecX project (inside TecX.Unity.Lifetime) which is taken from Mark Seemann's book Dependency Injection in .NET.