Android MVVM DataModel with Context - android

I am trying to learn & implement MVVM with databinding in my app. But I am facing difficulties in understanding/deciding few things.
I have one header view in my app which I need to use in multiple activities, so I basically created this
view_header.xml
HeaderViewModel.java (implements java.util.Observer)
HeaderDataModel.java (extends java.util.Observable)
where HeaderViewModel is bound with view_header.xml.
Now I include the view_header.xml in activity_xyz.xml & set ViewModel of Header View from that XyzActivity like this,
xyzViewBinding.setHeaderVm(new HeaderViewModel(new HeaderDataModel(mContext)));
Now I have questions based on this:
1) As HeaderDataModel needs context to work with SharedPreference & BroadcastReceiver, I initialize it inside the XyzActivity instead of HeaderViewModel- Is this correct approach?
2) I had to rely on broadcast receiver to update my header view, so I registered it inside the constructor of HeaderDataMode. Now as my HeaderDataModel is Observable, whenever I receive broadcast, I call notifyObservers() so that the observer(HeaderViewModel) detects it & updates it view.- Is this correct approach?
3) as I register receiver in constructor of HeaderDataModel, I created onDestroy() method inside data model where I unregister it & I call this onDestroy from XyzActivity’s onDestroy().- Is this correct approach?

As HeaderDataModel needs context to work with SharedPreference & BroadcastReceiver, I initialize it inside the XyzActivity instead of HeaderViewModel- Is this correct approach? - No, It is wrong. You must initialize it in HeaderDataModel so later on if you want to update HeaderDataModel, you can easily do it.
I had to rely on broadcast receiver to update my header view, so I registered it inside the constructor of HeaderDataMode. Now as my HeaderDataModel is Observable, whenever I receive broadcast, I call notifyObservers() so that the observer(HeaderViewModel) detects it & updates it view.- Is this correct approach? - Yes as i told it in first point.
as I register receiver in constructor of HeaderDataModel, I created onDestroy() method inside data model where I unregister it & I call this onDestroy from XyzActivity’s onDestroy().- Is this correct approach? - Yes. make public ondestroy() method in HeaderDataModel class.

Related

FirebaseMessagingService's onBind method is final. how make it bound service?

I want to bind my custom firebase service to the MainActivity class. if it was a normal service, it would be easily done by making the service implement the onBind method, but it is not available because this method is set final in the superclass of FirebaseMessagingService class. I want to bind the service in order to use the LiveData variable set inside this class in the MainActivity class.
I have searched for best practices here and read this documentation about bound services but no luck. I tend to use LiveData somehow but I feel it is not working until I somehow manage to bind the service. am I missing something?
As suggested in a comment by #CôngHải, I can use a singleton object with LiveData inside it to communicate between service and activity without the need of binding the service to activity.

Passing function from one activity to another via Broadcasts

I want to pass a function from one activity to another using Broadcasts. Like we can pass Strings and int by putExtra, Is there a way I can pass a whole function? I know there are other ways to do this, but I need to do this with the help of broadcasts. Any help?
Ex:
void myFunc(){ /* foo */ }
Can I use myFunc in some other activity via broadcast? I don't mind declaring the function again in the new activity as long as I get data from broadcast.
Is there a way I can pass a whole function?
No, sorry.
Can I use myFunc in some other activity via broadcast?
No, sorry.
Alternatives:
Use one activity rather than two
Have both activities work with some other object that is outside each of those activities (e.g., a singleton serving as a repository)

Can a service access a variable within an Activity?

I have an Activity called MainActivity that starts a Service called MainService. It is also binds the Service, so MainActivity can access methods and public variables within MainService. Is it possible to do it the other way round, i.e. the Service is able to access the Activity's methods?
I wish to implement it this way because I have a variable in MainActivity that is set upon onResume(), and on first startup the service has not yet started by the time onResume() runs, so at that point in time the service is still null.
This answer assumes that the Service in question runs in a different process:
Yes, it is possible. The general idea is that not only your Activity binds the remote Service through some AIDL defined interface, but it also implements additional AIDL interface which the Service is aware of, and sets itself as a callback target of the remote Service.
You'll have to have 2 AIDL files: the first one describes the interface of the Service, and the second one describes the interface of the Activity.
The implementation of such a scheme is very similar to "remote Service callbacks" described in this answer, though "callback" method would no longer be void, but return the value you're interested in.
Design considerations:
The above scheme will allow you to get values from Activity, but I don't think you should take this path. From the description of your use case, it looks that you only want to pass some value to the Service when Activity gets resumed. Since your Service is bound anyway, you can simply add a method setSomeValue(int value) to its AIDL definition and call this method from onServiceConnected() callback.
Yes it's possible.
You have to prepare method in your service to return back your activity just after service is bound:
public void bindActivity(MyActivity activity){...}
Then after service is bound to activity just call this method with MyActivity.this as parameter.
However...
You probably should not do it. Much more clear solution is using LocalBroadcastManager to pass events and data or use some more efficient solutions like Otto to do this same, but still - without direct access to one component's fields / methods from another.

Dynamic Broadcast Receiver in Fragment

Is it possible to dynamically register a broadcast receiver in a fragment to listen for connectivity state changes? If so how? If not, what are some workarounds for fragments?
EDIT: To register a BroadcastReceiver you need a Context. Since fragments live within activities, probably the best way to get a Context is to just use getActivity(). However, as gnorsilva explains below, there are certain special cases to look out for.
user853583 suggestion is a good one, but if you need access to a context inside a fragment you should use getActivity().getApplicationContext()
You should avoid passing an activity as a context whenever possible as this can introduce memory leaks - some object will hold on to that activity after its onDestroy() has been called and it won't be garbage collected.
Having said that, there are cases when you do need to pass an activity as a context - eg: for list adapters
Two more things though:
because a fragment is attached and detached from an activity, some times getActivity() returns null - you can call it safely inside certain lifecycle methods where you know an activity is alive eg: onResume()
if your fragment does not retain its instance i.e. is destroyed on orientation change, be sure to unregister your receiver in your fragment, for eg inside onPause() or onDestroy()
As far as I can see there is no way to register a BroadcastReceiver in a fragment. What do you need that broadcast receiver for? A nice solution is the one mentioned here
You can register a broadcast receiver like this :
getActivity().registerReceiver(...

Android IntentFilter for Every New Activity?

Is it possible to register a global broadcast receiver that gets notified every time a new activity is started (either by startActivity, startActivityForResult, etc)? What would the IntentFilter be?
EDIT: Just to clarify, I don't mean across apps I mean within my own app
You could potentially create your own partial subclass of Activity where it overrides onCreate(), onStart(), etc and manually calls a static/singleton instance of your global receiver as appropriate. After that, just derive your own activities' implementations from that subclass.
However, I'm assuming the reason you want to do this is that the "receiver" actually contains or otherwise represents some globally available state or resource - if you can find a way to implement your application without having any global state (and just passing it along as payload for an activity call, for instance), that would be best.
No, there is no way to do that.

Categories

Resources