nz.org.proverbio.android.loader.DataLoader.java Source code

Java tutorial

Introduction

Here is the source code for nz.org.proverbio.android.loader.DataLoader.java

Source

/*
 * Copyright (C) 2014 Android Development Community
 * Auckland, New Zealand
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package nz.org.proverbio.android.loader;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;

import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.RequestFuture;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import nz.org.proverbio.android.R;
import nz.org.proverbio.android.api.ServerApiCall;
import nz.org.proverbio.android.api.model.Message;
import nz.org.proverbio.android.context.ApplicationContext;
import nz.org.proverbio.android.network.JsonObjectRequest;
import nz.org.proverbio.android.network.NetworkManager;
import nz.org.proverbio.android.util.JsonManager;

/**
 * @author Juan Pablo Proverbio
 */
public class DataLoader extends AsyncTaskLoader<ServerApiCall> {
    private static final String TAG = DataLoader.class.getSimpleName();
    private static final ApplicationContext APPLICATION_CONTEXT = ApplicationContext.getInstance();
    private static final NetworkManager NETWORK_MANAGER = APPLICATION_CONTEXT.getNetworkManager();
    private static final JsonManager JSON_MANAGER = APPLICATION_CONTEXT.getJsonManager();

    private ServerApiCall mData;
    private ServerApiCall serverApiCall;

    public DataLoader(Context context, Bundle params) {
        super(context);

        serverApiCall = (ServerApiCall) params.getSerializable(ServerApiCall.class.getSimpleName());
        if (serverApiCall == null) {
            throw new IllegalStateException("The loader requires a api call to be performed");
        }
    }

    @Override
    public ServerApiCall loadInBackground() {
        RequestFuture<String> future = RequestFuture.newFuture();

        JsonObjectRequest request = new JsonObjectRequest(
                //Method
                serverApiCall.getHttpMethod(),
                //Url
                APPLICATION_CONTEXT.getString(R.string.server_url) + serverApiCall.getRequestPath(),
                //Data - This only supports POST and GET
                serverApiCall.getHttpMethod() == Request.Method.POST
                        ? JSON_MANAGER.toJSON(serverApiCall.getRequest().getMessage())
                        : null,
                future, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError volleyError) {
                        serverApiCall.getResponse().setError(volleyError);
                    }
                });

        NETWORK_MANAGER.getRequestQueue().add(request);

        try {
            String jsonResponse = future.get(20, TimeUnit.SECONDS);
            serverApiCall.getResponse()
                    .setResult((Message) JSON_MANAGER.fromJSON(jsonResponse, serverApiCall.getResponseType()));
            return serverApiCall;
        } catch (InterruptedException ie) {
            Log.e(TAG, "The request has been interrupted", ie);
        } catch (ExecutionException ee) {
            Log.e(TAG, ee.getMessage());
        } catch (TimeoutException te) {
            Log.e(TAG, "Timeout has occurred", te);
        }

        return serverApiCall;
    }

    @Override
    public void deliverResult(ServerApiCall data) {
        if (isReset()) {
            // The Loader has been reset; ignore the result and invalidate the data.
            releaseResources(data);
            return;
        }

        // Hold a reference to the old data so it doesn't get garbage collected.
        // We must protect it until the new data has been delivered.
        ServerApiCall oldData = mData;
        mData = data;

        if (isStarted()) {
            // If the Loader is in a started state, deliver the results to the
            // client. The superclass method does this for us.
            super.deliverResult(data);
        }

        // Invalidate the old data as we don't need it any more.
        if (oldData != null && oldData != data) {
            releaseResources(oldData);
        }
    }

    @Override
    protected void onStartLoading() {
        if (mData != null) {
            // Deliver any previously loaded data immediately.
            deliverResult(mData);
        }

        // Begin monitoring the underlying data source.
        ////if (mObserver == null) {
        ////mObserver = new SampleObserver();
        // TODO: register the observer
        ////}

        //// takeContentChanged() can still be implemented if you want
        ////     to mix your refreshing in that mechanism
        if (takeContentChanged() || mData == null) {
            // When the observer detects a change, it should call onContentChanged()
            // on the Loader, which will cause the next call to takeContentChanged()
            // to return true. If this is ever the case (or if the current data is
            // null), we force a new load.
            forceLoad();
        }
    }

    @Override
    protected void onStopLoading() {
        // The Loader is in a stopped state, so we should attempt to cancel the
        // current load (if there is one).
        cancelLoad();

        // Note that we leave the observer as is. Loaders in a stopped state
        // should still monitor the data source for changes so that the Loader
        // will know to force a new load if it is ever started again.
    }

    @Override
    protected void onReset() {
        // Ensure the loader has been stopped.
        onStopLoading();

        // At this point we can release the resources associated with 'mData'.
        if (mData != null) {
            releaseResources(mData);
            mData = null;
        }

        // The Loader is being reset, so we should stop monitoring for changes.
        ////if (mObserver != null) {
        // TODO: unregister the observer
        //// mObserver = null;
        ////}
    }

    @Override
    public void onCanceled(ServerApiCall data) {
        // Attempt to cancel the current asynchronous load.
        super.onCanceled(data);

        // The load has been canceled, so we should release the resources
        // associated with 'data'.
        releaseResources(data);
    }

    private void releaseResources(ServerApiCall data) {
        // For a simple List, there is nothing to do. For something like a Cursor, we
        // would close it in this method. All resources associated with the Loader
        // should be released here.
    }
}