I'm following this tutorial on how to use MQTT with Android Studio. In it, they created an MQTTClient class that uses the MQTTAndroidClient library. I want to pass the MQTTClient class from one activity to another. Any suggestions how I might do this? I'm new to Android dev and I'm trying to negotiate serializable/parcelable tools without much know-how. Thanks!
P.S. I'm developing in Kotlin
Passing complex classes between activities is generally a bad idea. For that kind of usage you should use a Singleton and store it in your Application class or something like this.
I don't recommend you to pass the entire MQTTClient through Activities.
I'd suggest you to read this Dependency-Injection manual is more or less what you need, normally you'd use a dependency injection library/framework to do what you want but since is complex to set-up most of them I'd follow the link I've linked before.
Sample code :
// Container of objects shared across the whole app
class AppContainer {
val mqttClient = MQTTClient() //<-- Initialisation
}
Then create a custom Application
class MyApplication : Application() {
// Instance of AppContainer that will be used by all the Activities of the app
val appContainer = AppContainer()
}
Do not forget to add it to manifest.xml with the name attribute.
And then from your Activity you need this MQTTClient you use :
val appContainer = (application as MyApplication).appContainer
val mqttClient = appContainer.mqttClient
What #Ben-J suggested is also a good point, to create a Singleton in kotlin you can use the object keyboard.
Related
I inject viewModels,repositories,fragments,Utils and ... but Is it good way to inject common class with dependency injection Koin or Dagger-hilt?
Suppose that we want to use StringBuilder() class in fragment
First approach :
We can inject it
val otherModule= module {
single { StringBuilder() }
}
And use it in fragment like this :
class Fragment : BaseFragment(){
private val mPassword : StringBuilder by inject()
}
Second approach :
We can create new instance without injection
class Fragment : BaseFragment(){
private var mPassword = StringBuilder()
}
My question is the first approach is common way for us ?
I'd say that it depends. The main goal / concept behind Di is to fulfil the firth principle of S.O.L.I.D, or as freecodecamp.org says:
It is the fifth principle of S.O.L.I.D — the five basic principles of
object-oriented programming and design by Uncle Bob — which states
that a class should depend on abstraction and not upon concretions (in
simple terms, hard-coded).
According to the principles, a class should concentrate on fulfilling
its responsibilities and not on creating objects that it requires to
fulfill those responsibilities. And that’s where dependency injection
comes into play: it provides the class with the required objects.
Another good answer is provided here, as it is already discussed when not to use dependency injection.
And now my opinion: If possible, try to inject those dependencies that you have to use quite often and if possible, inject them via constructor injection. With this, you can easily see, which dependencies are used by your class. Try not to inject classes that are used once or common language classes.
No, you wouldn't inject common language classes at all. There's no benefit to it. We inject classes when they need additional dependencies that we don't want to be creating ourselves, so we let the DI framework create them.
I have an abstract class and all classes in some package derive from it. Is there a way to create a list that dynamically instantiates all these classes that reside in some package when using Kotlin on Android?
Here is an example:
com.example.service
BaseService
com.example.service.emailservice
GmailService
OutlookService
All classes in com.example.service.emailservice derive from BaseService abstract class that resides in com.example.service. I want to create a list that contains GmailService and OutlookService objects. I could instantiate them manually and add them to a list, but in future I may add new service, lets say YandexService, which should appear in list too. This requires manual instantiation again. Is there a way to automatically instantiate classes that reside in some package?
There are two mayor ways to do it.
The first one - easier and dirtier one called Reflection.
You may find a lot of examples in java. Not so much in Kotlin though, but from what I have read here it is more than possible.
Usage of Reflection though, is not recommended in production, and generally considered as a bad approach to fulfill something.
The second way is Annotation Processors - this way is way harder. It is considered a clean way to do such tasks though and it is a general standard for code generating techniques. This way you can do all kinds of magic if you put your mind to it. Here is nice article about how to do it.
Generally I would recommend to use semiautomatic approach.
For example:
In your base service with init method
abstract class BaseService {
abstract fun init(): BaseService
}
Make all your services implement this BaseService
class Service : BaseService() {
override fun init(): BaseService {
return Service()
}
}
...
And then just create a list of classes
val services = listOf(Service(), Service1(), Service2())
and to init them do
services.forEach { it.init() }
This is not very different from what you have and may require some logical and architectural changes in your Services and App overall, but it won't be dirty and it won't require tremendous learning curve and time expenses.
Hope it helps.
use this library
add to gradle.build
implementation 'org.reflections:reflections:0.9.11'
then in your package com.example.service create a class from where you will be creating your Services, let's call it ServiceFactory here is implementation:
package com.example.service
import org.reflections.Reflections
class ServiceFactory {
init {
val reflections = Reflections(javaClass.`package`.name)
val subTypes = reflections.getSubTypesOf(BaseService::class.java)
val yourServices = subTypes.map { it.getConstructor().newInstance() }
yourServices.forEach { println(it.javaClass.name) }
}
}
fun main() {
ServiceFactory()
}
out:
com.example.service.emailservice.OutlookService
com.example.service.emailservice.GmailService
Something you were looking for ?
EDIT: of course you can instantiate this services from different place, but in that case you need to hardcode Reflections("com.example.service")
Interesting how difficult this answer is to find.
I've been using Dagger - Android for a while now and have my entire dependency graph set up. I'm using scopes, qualifiers, all that good stuff. I'm not a Dagger newbie anymore, but suffice to say I've been using it in a pretty standard way in my Android setup and everything has been going great.
For the first time, I'm realizing that I'd like to request new instances of a certain class in my graph myself, manually, and I want it to be a new instance every time.
What's the best way to go about doing that? I'm wondering if there's a way to leverage a non-#Singleton/non-scoped provider and call some sort of create() method myself, or if it's best to create a factory myself and make that factory a singleton/scoped instance and use my factory to get the new instance(s) when I need them? [I should mention this class will definitely not have an empty constructor so will need injected instances of other classes defined in my injection graph.]
(Also, it would probably help the most if answers were in the context of Android; i.e. I'm in, say, a ViewModel and need a new instance of some class defined in one of my Modules.)
Dagger will provide you a new instance as long as you don't scope the dependency.
To get a new instance of a dependency manually, you can inject Provider of it instead and use its get() method, it'll give you a new instance every time you call it.
Module part doesn't really change:
#Module
class AppModule {
#Provides
fun provideSomeObject(): SomeObject = SomeObject()
}
And in your class
class SomeClass {
// We don't inject the object anymore
// #Inject lateinit var myObject : SomeObject
// We'll inject it's provider
#Inject lateinit var myObject : Provider<SomeObject>
fun someMethod(){
// Here, instance1 and instance2 are NOT same objects
val instance1 = myObject.get()
val instance2 = myObject.get()
}
}
You can read more here.
I am trying to go through this android-architecture sample code :-
https://github.com/googlesamples/android-architecture/tree/todo-mvp-dagger/todoapp
I have read this user guide as well -
https://google.github.io/dagger/users-guide
This is the code in TasksRepositoryComponent
#Singleton
#Component(modules = {TasksRepositoryModule.class, ApplicationModule.class})
public interface TasksRepositoryComponent {
TasksRepository getTasksRepository();
}
ToDoApplication which extends Application has this code in onCreate() -
mRepositoryComponent = DaggerTasksRepositoryComponent.builder()
.applicationModule(new ApplicationModule((getApplicationContext())))
.build();
I can't understand a few things :-
Why doesn't TasksRepositoryComponent have an inject() method like other components in the app?
Why doesn't ToDoApplication also call the method tasksRepositoryModule() in DaggerTasksRepositoryComponent before build()? Why isn't that required?
Is there any place I can find a good documentation of rules to be obeyed while using dagger2?
Why doesn't TasksRepositoryComponent have aninject() method like
other components in the app?
TaskRepositoryComponent is a parent component with the sole purpose of publishing the binding for TaskRepository to its depedent components. The dependent components will inherit the binding for TaskRepository and be able to inject it into their injection sites. Have a look at the documentation for dependent components for more information about this feature.
Why doesn't ToDoApplication also call the method
tasksRepositoryModule() in DaggerTasksRepositoryComponent before
build()? Why isn't that required?
TasksRepositoryModule has a default public constructor with no parameters so the generated component can initialize it without it being explicitly constructed in the builder. Have a look at the generated code in DaggerTasksRepositoryComponent - you'll see something like
if (tasksRepositoryModule == null) {
tasksRepositoryModule = new TasksRepositoryModule();
}
I am fairly new to android and after reading a book and taking alot of tutorials i am about to create my first "real" app.
My question is rather simple does: Is the mediator design pattern still a good choice when designing android apps?
If yes is there any design patterns you should avoid when programming android apps?
if no is there any substitude to the mediator pattern you could use to have a collection of your instances of the different objects?
I suggest creating a model class (let's call it MyModel) and creating object of this class in Application.onCreate (not Activity.onCreate).
After that adding getter for that, so you can get this model from any Activity or Service like this:
MyApplication app = (MyApplication) getApplication();
MyModel model = app.getMyModel();
User user = model.getCurrentUser();
etc.
Also creating BaseActivity class can save you typing if you create method there protected MyModel getModel() which returns model from the first 2 lines of the code above.
Edit:
You need to create a class that extends Application and register this class in AndroidManifest.xml.
This is how: https://stackoverflow.com/a/2929927/2183804
Edit (about singleton):
It is said to be an anti-pattern (not only on Android). In Android I have seen people ending with singleton with accessor like MySingleton.getInstance(Context), because they needed Context anyway, e.g. for SharedPrefs or DB access. This is what Application is for, so there is no need to create additional, hackish entity, which could be used in a wrong way: MySingleton.getInstance(null) from a place where there is no Context available. This could lead to NPE after process is killed and restarted.