Keep app integrity when using asynchronous calls in android - android

I am trying to keep my app clean by using good design principles. I want to keep the view, the logic and the database layers separate.
On the app I am working on now, I have a main activity, a singleton, a logic class and a I use room for the database access. I would like the activity to tell the logic to fetch data from the database and then load it in the singleton. Once it is done I need the main activity to show the data loaded in the singleton.
Room use LiveData. How can I use LiveData and then somehow return a result to the logic layer then load it into the singleton and let the main activity now that it is ready?
More generally, how can I tell a caller, from the callee, that the data is ready when it is asynchronous? For example if the main activity calls a logic class in another thread to load data, how can the logic class then let the main activity know it is done?

You can use a Handler to update the main activity on the UI thread:
LogicClass.functionThatAccessesRoom() {
//get data from Room
//...
Handler handler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(#NonNull Message msg) {
//update the UI/views here
}
};
handler.obtainMessage().sendToTarget();
}

Related

How to receive data instantly with Architecture Compoenents?

I'm trying to implement the recommended architecture by Google and in a tutorial they show this diagram:
So I have a MainActivity and when the app starts it should go and fetch some data from the internet. I do those network operations in the Repository. Now my problem is that I don't know how to communicate properly between activities and Repository. For example MainActivity starts and immediately display a circular progress bar while Repository fetches the data. How can I stop the animation in MainActivity as soon as the data is inserted to the database? I guess I could call observe() on the LiveData and wait for onChanged(). Is there a better approach? What if there is no new data? Then onChanged() wouldn't be called...
Maybe I could send intent from Repository to MainActivity when there is no data so MainActivity knows it should stop the animation and if it doesn't receive the intent it just waits for onChanged()?
I guess I just don't feel confortable with the onChanged() method because I will never be sure of the operation it corresponds to. Maybe before the data from the network arrived there was some other data inserted which trigged onChanged() which would then stop the loading animation before it was supposed to.
Regarding your issue in the comments, which I believe to answer your main question also.
You need to observe from your UI (Activity / Fragment) to a progress LiveData in your ViewModel. That could be working with a Boolean (LiveData<Boolean>). To represent the progress view being visible or not.
That in turn needs to take an identical LiveData from the Repository (declared in the Repository as a MutableLiveData). You then post updates to the progress MutableLiveData in the Repository.
Now, whenever the MutableLiveData receives a change, that exists in your ViewModel as it shares the variable reference, and it will pass to the observer in your UI.
-
Alternatively, you could return a LiveData<Boolean> from the method in your Repository that pulls data. That would then be observable in your UI.
Instead of Boolean, you could also use a more complicated structure containing more information. A message, error code, etc.

Presenter having Handler in Android MVP pattern

Is it okay a presenter having Android Handler?
I know presenters should not have any Android related objects,
but I really don't have any clear answer.
Here's the thing,
this presenter runs a disk IO task on another thread,
meanwhile, the activity has to change its view.
These jobs are supposed to be done concurrently.
So I decided to pass the activity's handler as an argument
and let presenter send message to activity like this:
class FooPresenter: FooContract.Presenter {
…
private fun doDiskIOTask(handler: Handler) {
handler.sendEmptyMessage(0)
do_something_on_new_thread_and_join()
handler.sendEmptyMessage(1)
}
…
}
The activity has to know when the task is started and finished both and change view.
Could you tell me if I'm doing it any wrong or the better way?
Passing a Handler to the presenter doesn't sound like a good idea, you wouldn't be able to unit test it. I think a better approach would be to just call a method on the view and then run on UI thread from there. If your view interface is an Activity you can use the very convenient runOnUiThread method, e.g.
class MyActivity : AppCompatActivity, FooContract.View {
override fun emptyMessage0Method(){
runOnUiThread {
// manipulate views here
}
}
}

Android: Updating UI from thread in separate class

I am attempting to update a few UI elements in my app, after a separate class has been updated. The separate class is neither an activity nor a fragment. Could anyone point me in the right direction? Would a handler work well here, if so could you point me toward a acceptable example of handlers?
you can use this in a separe class.
public void setView(Activity activity, View view) {
activity.runOnUiThread(new Runnable() {
public void run()
{
/update your view here
}
});
}
You can get the view from your activity variable, instead of pass a view, if you prefere.
You cannot update any UI elements from a different thread than the main thread. If you are using the main thread, you can pass the View to the method in the other class and make some changes with that.
You need to link the two classes together by perhaps implementing a callback mechanism that will be processed using a handler into your main application thread, assuming that your external class can register a callback with the Activity class.
Or more simply you could use context by allowing a reference to be passed from the Activity to your other class, but you want to make sure you don't leak context.

Android singleton thread talking to server

This is mostly a design decision question.
I have an activity, a broadcast receiver, and a class that talks to my server (call it ServerAccess).
ServerAccess naturally needs to be in a thread of its own since it will be handling some network tasks. The activity needs to have its UI updated from the results of ServerAccess (so it needs some way to access the UI thread). The broadcast receiver also sends needs to send data to ServerAccess.
My question is, should I make ServerAccess a singleton thread? If so, how do you achieve that in Android? My reason for making it singleton is that every time any data exchange occurs from the server, I needs to query some basic user information from the server before I can start exchanging data. I would not like to query this basic user information every time the broadcast receiver receives a broadcast, or every time the activity is opened. Instead, I think a better idea would be to fetch the singleton ServerAccess if it is already created and start exchanging data. If ServerAccess was already instantiated then it would have already fetched that basic user information from the server.
Now would an AsyncTask be the way to go forward with this? Or to make a thread in my Application class like so? Or a singleton Service would be a better idea?
I do think you have to make it singleton. To make a singleton class create a static object of that class and then create a static method getInstance() and here if the object of the class is null then create the instance of the classs else return the instance ..
Example :
public class ServerAccess{
public static ServerAccess severAccess = null;
public static ServerAccess getInstance(){
if(serverAccess != null)return serverAccess;
serverAccess = new ServerAccess();
return serverAccess;
}
}

Android, understanding AsyncTask

Are specific AsyncTask's for specific activities? Or could I have say a RESTful APIManager which called one of four AsyncTask Classes, APIGET APIPOST APIPUT APIDELETE and be able to handle the network code that way? My idea is to be able to call something like this throughout my UI code.
<edit> Class UserPrefs;
APIManager.createUser(JSONObject info);
APIManager.createUser {
// handle info
APIPost newPost = new APIPost(info);
}
APIPost extends AsyncTask {
doInBackground {
//network code
<edit> UserPrefs.save(result);
}
}
Would this model be possible? Or am I misusing AsyncTask?
AsyncTasks are a natural fit for a RESTful service, but they are not tied to the lifecycle of Activities. You may create and start an Async task, but by the time the task finishes its background work and calls onPostExecute, the originating activity no longer exists in memory. Because of this, you should have a better plan for how to store local data than to keep it in an Activity member, where it can and will disappear frequently. To avoid thrashing, you should save the data somewhere. Candidates for saving local data are SharedPreferences, the file system, a database or the Application singleton object depending on the nature of the data and your app.
You could use ExecutorService, AsyncTasks are using it internally. Very easy to use.

Categories

Resources