updating UI with a volley request from a different class - java

I am having trouble with volley (again). I want to run a volley request in a class, so more than one activity can feed off its results and update their UI's accordingly. I have got it return data and call the request from the UI but now im struggling to update the UI with the new data. I have looked at answers but I'm trying to understand the structure and I am at a loss, can some please advise/ talk me through it

assuming I understand what you mean as being:
A Volley request returns, updates some data set through some activity
In this case, assuming the calling activity contains everything, and reminding that this is a very general example, what you should usually do (usually, since there are exceptions to the case), is just insert the data into the data set contained in your UI holder (e.g. your recycler adapter) and update it, an example would be your adapter holding a method similar to this:
public void updateDataSet(List<Item> items)
{
//mItemList is the adapters member list
if (null != mItemList)
{
mItemList.clear();
mItemList.addAll(items);
}
else
mItemList = items;
notifyDataSetChanged();
}
you call this inside the request callback you fired earlier, just make sure to initialize everything BEFORE you fire the request, e.g.
#Override
public void onResponse(JSONObject response)
{
Log.d(TAG + ": ", "somePostRequest Response : " + response.toString());
// here you need to parse to JSON to a list and then call...
List<Item> items = parseResponse(response);
myAdapter.updateDataSet(items);
}
Now, if what you meant was
A Volley request returns in some Activity, I want it to update stuff in another place
there are a couple of options:
As someone said in the comments - you could go for EventBus.
You could hold a DataManager class, which would be a global singleton, in which case you can either hold the data and update it there, and then every activity (in it's onResume or other relevant lifecycle method) knows to pull that data.
You could do the same as option 2, with the exception of that DataManager holding a reference to other UI parts (e.g. Fragments), and triggering member methods in them that pass the data and trigger the updates.
Personally I find option 3 cumbersome and somewhat bad practice, but if all else fails, (and it shouldn't, but if it does) then you can try.
There are more options out there, it depends and varies according to the data, your app architecture, coding style and other stuff you apply.
Hope this helps!

You can use EventBus. To use EventBus you need to register class where you will receive update and when you publish event for those event all classes will receive it.
Here is an example using greenrobot's EventBus :
Event Model :
public class MessageEvent {
/* Additional fields if needed */
}
Subscribe :
EventBus.getDefault().register(this); // In Activity onCreate method
#subscribe
public void onMessageEvent(MessageEvent event){
// this is the method to receive event
}
Publish event :
EventBus.getDefault().post(new MessageEvent());
Now every class subscribed for this event model will be updated.
Note : subscribed classes have to alive, If anyone destroyed they won't receive update.

Related

RxJava Observable that emits latest value upon subscription

I am building an Android MVVM application using RxJava2. What I want is to expose an Observable in my ViewModel, which I also can receive the last emitted value (like a BehaviourSubject). I don't want to expose a BehaviourSubject because I don't want the View to be able to call onNext().
For example, in my ViewModel I expose a date. I now want to subscribe a TextView to changes, but I also need to be able to access the current value if I want to show a DatePickerDialog with this date as initial value.
What would be the best way to achieve this?
Delegate:
class TimeSource {
final BehaviorSubject<Long> lastTime = BehaviorSubject.createDefault(
System.currentTimeMillis());
public Observable<Long> timeAsObservable() {
return lastTime;
}
public Long getLastTime() {
return lastTime.getValue();
}
/** internal only */
void updateTime(Long newTime) {
lastTime.onNext(newTime);
}
}
I don't want to expose a BehaviourSubject
Subject, by definition, is "an Observer and an Observable at the same time". Therefore, instead of exposing BehaviorSubject itself just expose Observable, thus client (in this case the view) won't be able to perform onNext(), but will be able to receive last emitted value.
As an alternative to subject approach you can use replay(1).autoConnect() approach. See more details concerning this approach in "RxJava by example" presentation by Kaushik Gopal.
Also, consider cache() operator (see difference of cache and replay().autoConnect() here).

How to update UI for callback received while app is in background?

I am creating an android application using MVP architecture. I have created Presenter and Interactor classes. I am struggling to update UI when app is in background and comes back to foreground.
Let's consider following scenario.
Button on UI is clicked and presenter is notified about it. Presenter asked Interactor to provide data from backend. By the time Interactor provides result to presenter somehow UI is in background. How can I save the state of it and change UI components once app is in foreground.
I tried doing following things:
Using flags (turn on the flag and check in onResume to call the method that supposed to be called when callback received. But problem is that let's say if I have 5 different services that can be called by presenter which has different callback then I will require 5 flags which I don't like it)
Using JAVA reflection (Store the name of method be called in HashMap with parameter)
Is there any better way to achieve this?
As name MVP Suggests Model View Presenter
Model : Model is responsible for getter setter methods also known as POJO.
View : Contains activities/fragments with views.
Presenter : Actual Business Logic where you can communicate network calls OR relate with backend databases such as SQLite / MySql.
When button click you need to call presenter which will perform background tasks once it is done you need to notify your view that the response is Success/Failure via CallBacks which done with the help of interfaces.
Example:
interface BaseContract {
interface BaseView {
//Methods for View
void onDoSomething();
}
interface BasePresenter {
void doSomething();
}
}
class BaseMainPresenter implements BaseContract.BasePresenter {
BaseContract.BaseView view;
BaseMainPresenter(BaseContract.BaseView view) {
this.view = view;
}
#Override
public void doSomething() {
if (view != null)
view.onDoSomething();
}
}
class DemoClass implements BaseContract.BaseView {
//Create object of Presenter
/****
* Example :
* BaseMainPresenter baseMainPresenter = new BaseMainPresenter(this);
*/
#Override
public void onDoSomething() {
//Deal with Context here.
}
}
You could add some "pause" logic to your presenter:
Whenever the UI goes to background, you tell the presenter to "pause" and to save any data being received to a cache (could be as simple as a list inside your presenter).
Whenever the UI is back to foreground, you tell your presenter to unpause and to unload its cache to the UI (if the cache list is not null it pushes it to the UI, just like a regular response received by your interactor)

How can I know when an object has performed an action?

I'd like to create a Service that's capable of creating a number of objects, where each object connects to the internet and downloads some JSON data and a photo. Most of this is pretty straight forward, but I want it to happen one at a time, i.e. a new object cannot be created until the first object has completed its actions.
What's the best way for my Service to know when an object has performed its actions?
Here's a very rough illustration of what I'm looking for:
Use an IntentService. In normal usage, each Intent it receives is processed sequentially and is already in a background thread, so you don't even need to do your network activity in an AsyncTask. Easy.
Alternately, put all your things in a Queue and have the "do next thing" call happen as a result of the onPostExecute() call in AsyncTasks.
Queue<YourObject> unfinished = getQueue();
List<YourObject> finished = new LinkedList<YourObject>();
Handler handler = new Handler(){
handleMessage(Message m){
// Object populated! Start next? Blink lights? Whatever.
}
}
AsyncTask t = new AsyncTask<...>(handler) {
Handler h;
public AsyncTask<...>(Handler h) {
this.h = h;
}
protected V doInBackground(YourObject o) {
// Network stuff, populate the thing
return popualtedThing();
}
protected V onPostExecute(YourObject o) {
h.sendMessage(Message.obtain(0,o);
}
}.execute();
How about this? When the object creation is complete, broadcast an intent (you could use LocalBroadcast for example, if you want it to be private).
In your Service, register for the above mentioned broadcast, and when it is received, perform the next task.
Use listeners. Have the background service register as a listener to the object instance and when the object instance is does it just calls back to all the listeners.

How to make a callback from a Service to an Activity

Sorry for bugging you again, but I still can't find a way to make a callback from my activity to a service...
Found a similar question - How to Define Callbacks in Android?
// The callback interface
interface MyCallback {
void callbackCall();
}
// The class that takes the callback
class Worker {
MyCallback callback;
void onEvent() {
callback.callbackCall();
}
}
// Option 1:
class Callback implements MyCallback {
void callback() {
// callback code goes here
}
}
worker.callback = new Callback();
yet not sure how to integrate that sample into my project.
Any suggestions or links to clear tutorials would be great!
That kind of callbacks (Observer pattern) that you are showing in your example won't work between a service and an activity. Use observer patter when, from class A, you created the instance of class B and want to send callbacks from B to A.
With regards to the services and activities, things are completely different. AFAICT, if you want to callback your Activity from a Service, the best method to achieve this is to use ResultReceiver. There are a lot of interesting things about ResultReceiver:
Its constructor receives a Handler (that you must create inside the activity), which will allow you to change UI from the service.
It implements Parcelable thus you can put a reference of your ResultReceiver in the Intent extras that you used to start the service.
Its onReceive method has a result code integer which allows you to generate different kind of callbacks (this is like if your callback interface had many methods). Also, it receives a Bundle which you can use to put all result data.
On the other hand, if you want to do a callback (not sure if that is correct term in this case), from your Activity to your Service, I guess you will have to send a Broadcast message or something like that.

Differentiate events for multiple attached gwt widgets

I've been trying to make multiple Presenters "listen" to the same event but I which to make each event unique to the Presenter.
Ex.
I create 3 Composite widgets each in one different tab. They get all attached to the same event at binding. Let's call it the "NewPrescriptionEvent". If this event is fired, all my 3 composites will try to DO the job. I only want one of them to do it.
The only way I found to do this is by creating a temp event id (an integer inside the event) which I check for each widget which is trying to respond to the event.
Code snippet
private class OnNewPrescription implements NewPrescriptionHandler {
#Override
public void onNewPrescription(NewPrescriptionEvent event, int dataObjectId) {
if (getDataObject().getPatientId() == dataObjectId) {
...
}
}
}
During binding I do the usual:
eventBus.addHandler(NewPrescriptionEvent.TYPE, new OnNewPrescription());
The event:
public class NewPrescriptionEvent extends GwtEvent<NewPrescriptionHandler> {
public static final GwtEvent.Type<NewPrescriptionHandler> TYPE = new GwtEvent.Type<NewPrescriptionHandler>();
private int dataObjectId;
public NewPrescriptionEvent(int dataObjectId) {
this.dataObjectId = dataObjectId;
}
#Override
protected void dispatch(NewPrescriptionHandler handler) {
handler.onNewPrescription(this, dataObjectId);
}
#Override
public GwtEvent.Type<NewPrescriptionHandler> getAssociatedType() {
return TYPE;
}
}
I was thinking that the TYPE need to be different each time but still be the same event. Does anyone have a suggestion?
Thx.
Is it the case that you have an arbitrary number of instances of the same presenter and all are listening to the same event type? And each of your presenters 'controls' a different entity an therefore should only react on events coming from that entity? If that's the case the only solution I see is to parametrize the event as you've done.
Sounds like the EventBus probably isn't the best approach here; this is one of the main problems I've personally had with the EventBus: all events are global, and it's hard to differentiate between different events of a given type.
A good set of rules for asynchronous event handling without a shared EventBus is:
Communicate with child widgets via direct method calls.
Communicate with a parent widget via callbacks/handlers/listeners.
Avoid direct knowledge of sibling widgets (probably beside the point here)
So, the widget that contains the 3 tabs can attach callbacks to each tab that, when called, dispatches each event to its appropriate event handler (Presenters, in your case, I believe).
No global communication required, no knowledge of sources or destinations, only one event type, one reusable tab widget type, and the tab class stays simple. In principle, not too different from adding a ValueChangeHandler to a CheckBox (after all, one doesn't subscribe to check box events via the event bus, you just add a handler directly to the widget).
Rough sketch:
public class TabContainer implements IsWidget {
public TabContainer() {
tab1.addNewPrescriptionHandler(
new NewPrescriptionEventHandler() {
#Override
public void handleNewPrescriptionEvent(NewPrescriptionEvent event) {
handleTab1Event(event);
}
});
tab2.addNewPrescriptionHandler(
new NewPrescriptionEventHandler() {
#Override
public void handleNewPrescriptionEvent(NewPrescriptionEvent event) {
handleTab2Event(event);
}
});
...
}
}
And you might even be able to simplify that with some looping and pairing.
Going the other way, this container can also send events back the other way to your widgets from wherever else using the same principles.
Also, depending on what the Event class contains, you might not even need an Event class; you can define your callbacks and params however you want.
I think the title of the question is your answer.
You need different event types for each of the widgets.
You could try using addHandlerToSource(GwtEvent.Type<H> type, Object source, H handler) if you know the source to listen to.
Another possibility would be to extend EventBus to accept some kind of filter on registration.

Categories