I need a variable accessed and updated by two or more services or activities. I am thinking of using interface. A class that implements that interface to be initialized in Base Application class or via hilt. I am not entirely sure how to do that.
Is this possible and if so, is this good idea?
Can I use any other way to pass variable from service to service or activity to service?
Possible psuedoCode for idea.
interface foo(){
variable a
fun setA(var : p)
}
class JustAClass: foo{
variable a;
fun setA(var : p){
a = p
}
}
BaseApp(): Application(){
JustAClass jac = JustAClass();
}
activityA(){
BaseApp.jac.setA(99)
}
serviceB(){
variable c = BaseApp.jac.a
}
Yes, you could do it the way you describe, but there are a few easier ways...
You can use a Singleton. In Kotlin, any Object is automatically a statically accessible Singleton. So, something like this:
object SharedData{
var item1 = "test"
var item2 = false
}
can be accessed anywhere in your app by using SharedData.item1 or SharedData.item2. You can also make those variables into LiveData or Kotlin Flow if you want to post updates and observe them between activities/services/etc.
You can also store your data in SharedPreferences. It'll provide more permanent storage that will survive app restarts, but it reads and writes data to internal storage, so you need to deal with IO overhead.
You can also store your data in other permament data structures, like a Room Database, but I think that would be overkill for just communicating between processes.
Related
Currently, I have a database manager class that handles all operations to the database like this:
class DatabaseManager(val context: Context) {
private val db = Firebase.firestore
//Other functions, etc.
}
It makes use of the context passed in by different activities to perform functions to the database. The thing is, every single activity that requires database functions have to instantiate this manager class first, then call the functions. I would like to make use of the Singelton design pattern to make it such that all the activities will only use a single instance of the class. I believe kotlin's objects can do this, however I also need to be able to pass in the context of the activities into this manager class. Any assistance is appreciated, thank you!
I would recommend not doing that. The problem with Singletons is that they make code hard to test, you can't fake out the database. And for a database this is a particularly bad problem, as setting up all the right fake data can be painful. Instead, take a look at injection. It can do the same thing (make a single instance shared between everyone who needs it), but it manages that global state rather than having the classes themselves manage it via a static reference, passing it in (generally via the constructor) to whoever needs it. This makes it easy to provide an alternative or mock database when needed for testing. Injection used to be a bit painful to set up, but Hilt makes it a lot easier these days.
When I developed android app with Java I used EventBus , then I used java.util.observable to listen some var without getting a reference of a class/service.
For example, I could listen in ViewModel/Activity some var from a service without getting instance of that service.
I did it before I started using Clean Architecture, SOLID, MVVM etc.
Now I am using widely LiveData and ViewModel pattern, and Dependency Injection with Dagger2. So, every time I have a reference to listen a LiveData var.
I am wandering if exist in Kotlin a way to listen a var in one class from another class without getting an another class's reference?
This is not practical question, it's just curiosity
For listening to data from a variable just use LiveData.
wrap your variable in LiveData and use an observer to observe data changes to it.
Also if your variable is somewhere in a class which you don't want to create object of. Then you can simply wrap that variable in companion object like this.
class Test() {
companion object {
var testvariable = "Hello"
}
}
then simply call it like this "Test.testvariable"
I am new to android MVP pattern and working on my project i have some basic problem related to Android Context in the presenter. Although there are many answers related to this but i didn't get a perfect one which can solve my problem.
I have following queries:
how to access shared preferences inside presenter.
how to access other system services inside presenter.
if i am working on SQLite Databases then during any transaction in my database which is done by call from presenter to my SQLite Helper class need context to access database.
If i will pass my activity context in presenter then it will a problem during unit testing, also it is a violation according to MVP Format.
I need a perfect solution so that my code quality is not degraded.
Note: I dont want to use dagger tool so the answer should be dagger independent
In MVP you dont use Context or anything else from the Android SDK/Framework in the Presenter (P) layer! This layer is for anything else than Android related stuff.
1) how to access shared preferences inside presenter.
You don't. If you need a value from a SharedPrefences in the Presenter then you could pass the value to the Presenter via a method call.
Example:
class MainActivity{
String birthday = SharedPrefence.getString(..);
presenter.setSavedBirtday(birthday);
}
2) how to access other system services inside presenter.
As metioned before; You don't acesss System services in the Presenter.
What you can do is call the a System Service from the Presenter.
Example with Vibrator:
1 - Create an interface:
interface OnSystemServiceCaller{
onVibratorCall();
}
2 - Implement it in a Activity
class MainActivity implements OnSystemServiceCaller{
#Override
onVibratorCall(){
Vibrator v = (Vibrator) getSystemService(VIBRATOR);
v.vibrate(50);
}
}
3 - Call from presenter
class Presenter{
OnSystemServiceCaller listener;
public void ifButtonClicked(){
listener.onVibrateCall();
}
}
3) if i am working on SQLite Databases then during any transaction in my database which is done by call from presenter to my SQLite Helper class need context to access database.
Some wont like this answers other will, this is just a suggestion.
You can access your SQLite by using a global ApplicationContext() in your app class (Class that extend Application; see how here since your SQLlite is global for the whole app and not just a particular Activity And when you need to pass data from SQLite to a Activity then you pass it first to the Presenter and from Presenter to your Activity the same way we send a call to our Vibrator method
I'm developing an Android app that uses two singleton objects: one for business logic (similar to the model in MVC) and one for a Bluetooth connection. Some activities display data and need access to the former, while one lets the user connect/disconnect and needs access to the latter.
What is the preferred way of passing these objects around? Arguments to the activities? Global objects?
You can use Application Class. it is a base class for those who need to maintain global application state. You can provide your own implementation by specifying its name in your AndroidManifest.xml's tag, which will cause that class to be instantiated for you when the process for your application/package is created.
There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context ,the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.
ref- http://developer.android.com/reference/android/app/Application.html
Ex- Define in App class
public class AppData extends Application{
Object ob = new Object(); //Global Obj - Can be anything String etc
}
initialize in acticity like -
AppData ad= (AppData)getApplicationContext();
ad.ob = //yourValue
Access across the activities ->
Object obj = ((AppData)getApplicationContext()).ob;
and in manifest give the name of your app class-
<application
android:name=".AppData"
>
You might want to check out Dagger. This Dependency Injection framework (optimized for Android) allows to easily inject singletons into your activities/fragments.
// define this code in your common data access class which use thought your app or application master class
private static Object object=null;
public synchronized static Object getInstance(){
if(object==null){
object = new Object();
}
return object;
}
// this way define your two object.
I'm trying to persist data objects throughout my Android app. I want to be able to access an object in one activity, modify it, save it, navigate to a new activity, and access the same object with the updated value.
What I'm essentially talking about is a cache, but my data objects are complex. For example, ObjectA contains ObjectB which contains ObjectC. Does anyone know if a good method, tool, or framework for persisting complex objects in Sql?
Put a static field in a subclassed Application. Also inside your manifest, put:
android:name="MyApp" inside your application tags.
Also to access from other files, simply use:
MyApp myApp = (MyApp)getApplicationContext();
See here How to declare global variables in Android?:
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
#Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
You could use an ORM framework, like OrmLite for mapping objects into sql, but it may be an overkill for you situation.
You could also make these shared object Parcelable and pass them between the Activities thru the Intents.
You could also save these objects into the SharedPreferences, so each Activity can access them whenever they feel the need to it, and the objects are also persisted this way. This may mean more IO access though, so take that into consideration as well. You could use e.g. Gson to serialize the objects more painlessly for this.
These are the solutions I'd consider. But whatever you do, don't put this common object into some kind of "standard" global static variable, like using a custom Application class, static field or any implementation of the Singleton pattern, these are really fragile constructs on Android.
Why don't you use a JSON serialization mechanism ?
In association with a static access to your objects you can easily build a lite-weight database with some basic functionnalities:
loadObjectsFromCache
saveObjectsInCache
getObjects
You can also store your objects in differents files, and use a streaming json parser like this one: http://code.google.com/p/google-gson/
It's the same that this one: http://developer.android.com/reference/android/util/JsonReader.html
but can be used even if your application api level is inferior to 11.
It use less memory than the basic DOM parser:
http://developer.android.com/reference/org/json/JSONObject.html,
but with the same speed.