Search code examples
androidandroid-fragmentshttpconnectionandroid-fragmentactivity

What is the best way to use a fragment with httpconnection?


I'm doing the refactoring of an application that uses AsyncTask to make HTTP calls to a web service.

Now use a simple Activity, at the moment when I needs to invoke the service using a AsyncTask in this way:

  private class MyAsyncTask extends AsyncTask {<String, Void, Boolean>
    private ProgressDialog progressDialog;


    private xmlHandler handler;

    @ Override
    protected void OnPreExecute () {
    progressDialog = new ProgressDialog (home.This);
    progressDialog
    . SetMessage (getString (R.string.home_loadinfo_attendere));
    progressDialog.setCancelable (false);
    progressDialog.show ();
    }

    @ Override
    protected Boolean doInBackground (String... params) {
    try {
    xmlHandler handler = new XmlHandler();
    return Service
    . GetInstance ()
    . CallService (
    ServiceType.GETINFO,
    Home.This, handler, null);
    } Catch (Exception e) {
    e.printStackTrace ();
    return false;
    }
    }

    @ Override
    protected void OnPostExecute (Boolean success) {
    progressDialog.dismiss ();

    String message = null;
    if (success | | (handler == null))
    message = getString (R.string.server_result_msg500);
    else {
    switch (handler.getStatusCode ()) {
    case 200:
    doStuffWithHandler(handler);
    return;
    case 500:
    message = getString (R.string.server_result_msg500);
    break;
    case 520:
    message = getString (R.string.server_result_msg520);
    break;
    default:
    message = getString (R.string.server_result_msg500);
    break;

    }
    }

    if (message! = null) {

    AlertDialog.Builder builder = new AlertDialog.Builder (home.This);
    builder.setTitle (R.string.home_loadinfo_error_title)
    . SetMessage (message)
    . SetCancelable (true)
    . SetNegativeButton (R.string.close_title,
    new DialogInterface.OnClickListener () {
    @ Override
    public void onClick (DialogInterface dialog,
    int id) {
    dialog.cancel ();

    }
    });
    AlertDialog alert = builder.create ();
    Alert.show ();
    }
    }
    }

 doStuffWithHandler(handler){

// populate interface with data from service

 }

I want to do the same but using Android compatibility libraries and FragmentActivity. I read a little about loader but I did not understand how I could use them in this same way, Could you please tell me if this is the right way (FragmentActivity, Fragment and Loader) and how to implement it also addresses giving me examples?


Solution

  • You could create a Loader, something like this:

    public abstract class MyLoader extends AsyncTaskLoader<String> {
    public MyLoader(Context context) {
        super(context);
    }
    
    private String result;
    protected String error;
    
    @Override
    public final String loadInBackground() {
        try {
            error = null;
            // Load your data from the server using HTTP
            ...
            result = ...
            ...
            return result;
        }
        catch (Exception e) {
            Logger.e("ResourceLoader", "Loading resource failed.", e);
            error = e.getMessage();
        }
        return null;
    }
    
    @Override
    protected void onStartLoading() {
        if (!TextUtils.isEmpty(error)) {
            deliverResult(result);
        }
    
        if (takeContentChanged()) {
            forceLoad();
        }
    }
    
    @Override
    public void deliverResult(String data) {
        if (isReset()) {
            return;
        }
    
        result = data;
    
        if (isStarted()) {
            try {
                super.deliverResult(data);
            }
            catch(Exception e) { 
                Log.e("ResourceLoader", "Caught exception while delivering result.", e);
            }
        }
    }
    
    public String getError() {
        return error;
    }
    }
    

    In your Fragment, you can initialize this loader:

    public class MyLoaderFragment extends Fragment implements LoaderCallbacks<String> {
    ....
    ....
    String message;
    
        @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        setRetainInstance(true);
            ....
    }
    
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getLoaderManager().initLoader(0, getArguments(), this);
    }
    
    @Override
    public Loader<String> onCreateLoader(int id, Bundle args) {
        return new MyLoader(getActivity());
    }
    
    @Override
    public void onLoadFinished(Loader<String> loader, String result) {
        // Here you have the result in 'result'.
        message = result;
        ...
    }
    ....
    }
    

    And instead of just returning a simple 'String' result, you can return any object you like. Just adjust the MyLoader and LoaderCallbacks implementation accordingly.