Java tutorial
/* * 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. } }