android, REST, Web Services

Android and RESTful request made easier (yeah using Volley)

Hey, I know it’s been a while but as usual, my excuse is I don’t have enough time to write here 🙂

This time I’d like to update some old concepts with new technologies: I’ve been working on the Android platform for a while and things evolve way too fast ! This tutorial will help you build some nice structures to fetch data from RESTful web services.

This article will not cover all the HTTP Verbs but I have laid the bases for you to easily implement them. Like my other articles, I’m going to assume you have background on Android development and you understand some programming patterns (specially the Singleton pattern).

Let’s get started:

We will build a incredible simple single page application that will make a RESTful request and will show the results. I’ve seen quite a lot of example on how to achieve this and quite frankly I cannot believe how hard some people are making this look.  The base Architecture for our app is as follows:

We will have a connector object that will obtain the data from the web service. This object will use a Singleton pattern and will inherit from the Observable class. The idea is that when we require data from the server, we will ask the instance to fetch it in a separate thread and once we have the results we will update the UI (remember, the app will crash if you try to do networking on the main thread).

We will use the following GET url: https://jsonplaceholder.typicode.com/posts

We will create a DTO object to map those post (just for the sake of simplicity):

public class Post {
    public int userId;
    public int id;
    public String title;
    public String body;
}

And this is how our Connector will look:

public class PostConnector extends Observable {

    private static final String ENDPOINT_GET_POSTS = "https://jsonplaceholder.typicode.com/posts";

    private static PostConnector instance = new PostConnector();

    public static PostConnector getInstance() {
        return instance;
    }

    private PostConnector() {
    }
}

Nothing too complicated so far. Basically we have class that cannot be instantiated (private constructor) from outside, but you can access the only instance through the public method getInstance().

If you are somewhat familiar with Volley you know (or should know) how requests are put in a queue. We want to avoid the creation of multiple queues and in order to do so, we will create a dispatcher that will take request globally. We will use a Singleton again:

public class VolleyDispatcher {

    private VolleyDispatcher() {
    }

    private static VolleyDispatcher instance = new VolleyDispatcher();

    public static VolleyDispatcher getInstance() {
        return instance;
    }

    // application's main queue
    private RequestQueue requestQueue;

    // since multiple threads may be accessing this, let's make it synchronized
    public synchronized void addToQueue(MainActivity context, Request request) {
        if (requestQueue == null)
            requestQueue = Volley.newRequestQueue(context);

        requestQueue.add(request);
    }
}

Now we can take a look at the “getPosts()” method on our Connector:

/***
 * Get posts from the web service
 * @param context
 */
public void getPosts(final MainActivity context) {
    // let's not mess with the UI thread
    new Thread(new Runnable() {
        @Override
        public void run() {

            JsonArrayRequest jsonObjectRequest = new JsonArrayRequest(Request.Method.GET, ENDPOINT_GET_POSTS, null,
                    new Response.Listener<JSONArray>() {
                        @Override
                        public void onResponse(JSONArray response) {
                            if (response != null) {
                                // this is what we are looking for !
                                ArrayList<Post> result = new ArrayList<>();

                                try {
                                    for (int i = 0; i < response.length(); i++) {
                                        JSONObject current = response.getJSONObject(i);
                                        Post post = new Post();
                                        post.id = current.getInt("id");
                                        post.userId = current.getInt("userId");
                                        post.body = current.getString("body");
                                        post.title = current.getString("title");
                                        result.add(post);
                                    }
                                } catch (JSONException ex) {
                                    Log.d(PostConnector.class.getSimpleName(), ex.getMessage());
                                    setChanged();
                                    notifyObservers(null);
                                }

                                // all good! let's notify the results
                                setChanged();
                                notifyObservers(result);
                            }
                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            setChanged();
                            notifyObservers(null);
                        }
                    }
            );

            VolleyDispatcher.getInstance().addToQueue(context, jsonObjectRequest);
        }
    }).start();
}

This part is easy: we create a new thread to avoid locking crashing the app. We create and queue the requests later. The rest of the code is a very simplistic use of the Observer pattern: notice the setchanged() and the notifyObservers() calls. That will let any object observing this one that something is ready (or not).

Observer Pattern in a nutshell

observer_pattern.png

To use this approach all you have to do is have an object observing and processing  (via the Observer’s update implementation) the results. I did this implementing the Observer interface on the MainActivity (you can do this on fragments too!). Just be careful with those memory leaks ! pay attention on how to remove the observer when the app goes to background (use OnDetroy if you still want networking on the background).

public class MainActivity extends AppCompatActivity implements Observer {

    private final Handler mHandler = new Handler(Looper.getMainLooper());
    private Button getPostsButton;
    private ListView postsList;
    private ArrayList<String> postTitles = new ArrayList<>();
    private ArrayAdapter<String> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getPostsButton = (Button) findViewById(R.id.get_posts_button);
        getPostsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                PostConnector.getInstance().getPosts(MainActivity.this);
            }
        });

        // list related stuff
        postsList = (ListView) findViewById(R.id.posts_list);
        adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, postTitles);
        postsList.setAdapter(adapter);
    }

    @Override
    protected void onResume() {
        super.onResume();
        PostConnector.getInstance().addObserver(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        PostConnector.getInstance().deleteObserver(this);
    }

    @Override
    public void update(Observable observable, final Object o) {

        // use the MainLooper to post stuff back to the UI !!!!
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                // we are ready to update the ui
                if (o != null) {
                    postTitles.clear();
                    ArrayList<Post> posts = (ArrayList<Post>) o;
                    for(Post current : posts){
                        postTitles.add(current.title);
                    }
                    adapter.notifyDataSetChanged();
                }
            }
        });
    }
}

That’s it ! The reason I believe it’s simpler to have connector classes and Singletons is because I find the use of AsynkTasks messy and a bit more hard to control. Not to talk when the Main Activity dies but the tasks is still executing stuff….

You can get the source code for this example from:

https://github.com/aarcoraci/android-restful-2017

observer_pattern.png

2 thoughts on “Android and RESTful request made easier (yeah using Volley)”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s