I want to separate async http code from the activities as I'm reusing the code. This is what I am doing currently:
I want to get a list of projects form a REST API and store it in an array. (Assume I'm not using local caching as I want to load them every time)
ProjectInterface.java
public interface ProjectInterface {
public void onProjectsLoaded(ArrayList<Project> projectArrayList);
}
HttpProjectList.java
//async class will get the results from the server and send to the activity
public class HttpProjectList {
protected ProjectInterface interface;
protected Context c;
public HttpProjectList(ProjectInterface interface, Context c){
this.interface = interface;
this.c = c;
}
//Run Async task Volley here
public void projectListRequest() {
RequestQueue requestQueue = Volley.newRequestQueue(this.c);
JsonArrayRequest req = new JsonArrayRequest(Path.WORK_ORDERS, success, error);
requestQueue.add(req);
}
//on success set the data
private Response.Listener<JSONArray> success = new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
//do dome parsing here and populate the array
interface.onProjectsLoaded(projectArrayList);
}
}
//error function here, i'm not typing
}
MyActivity.java
//I'm calling all in this activity
public class BaseActivity extends Activity implements ProjectInterface {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(setView());
HttpProjectList httpList = new HttpProjectList(this, getBaseContext());
httpList.projectListRequest(); //fire http call
}
//run after projects loaded
@Override
public void onProjectsLoaded(ArrayList<Project> projectArrayList) {
//Do something with the server data
}
}
In this case I have one API that populate the array. What if I have multiple api calls? Like
How can I organise code according to OOP and SOLID principles? These are the techniques I have In my mind, but I don't know which one is the best.
Create separate classes for all the Async functions. According to the above example I have 1 interface and 1 http service handler class. In the same way, I will create 2 sets of classes for every api call
Create one interface call HttpInterface and put all the call back functions in it, and create another HttpHandler class and put all the http methods of all the API calls
Which one is better? Or is there any other way? Can you give some advice on this? Thanks a lot!
Both your suggested approaches follow the Observer´s pattern. I would personally suggest the second approach where all the methods are encapsulated in one single interface. However, if the number of methods rises (lets say above 5) then maybe you need to consider to group them in a way that may reflect the functionality of an object. For example you might have:
public interface HttpUserListener {
public void onUserListReceived(List<User> users);
public void onUserAdd(User user);
public void onUserRemove(User user);
}
public interface HttpProjectListener {
public void onProjectListReceived(List<Project> projects);
public void onProjectAssigned(Project project, User user);
public void onProjectComplete(Project project);
}
On the implementation part probably you need a List of listeners to be called on particular event:
public class HttpHandler {
protected List<HttpUserListener> userListeners;
protected List<HttpProjectListener> projectListeners;
protected Context c;
public HttpHandler(Context c){
this.c = c;
}
public void registerListener(UserListener listener){
if(userListeners == null){
userListeners = new ArrayList<UserListener>(1);
}
userListener.add(listener);
}
public void unregisterListener(UserListener listener){
if(userListeners == null){
return;
}
userListener.remove(listener);
}
public void asyncAddUser(User user){
// provide the async method and call the listeners
if(userListeners != null)
for(UserListener l: userListeners)
l.onUserAdd(user);
}
}
I want to emphasize that the ideal place of creating and handling async tasks in Android are Services. so the HttpHandler
would extend a Service
(or IntentService
which already provides a worker thread) and you can register and unregister listeners to this service by using binding approach. This is a good tutorial from Android developers website.
Alternatively you can forget about the traditional listener´s approach and have a single service which will broadcast intents when an HTTP call takes place. And have your activities capture these broadcasts and react accordingly. This is closer to Android´s programming architecture.