开发者

Android, how can i encapsulate an AsyncTask class with network connections

开发者 https://www.devze.com 2023-04-08 19:17 出处:网络
Im starting with android (3 days ago) and i cant get the solution for what i want. So, i read a lot of threads here about asyncTask and now im sure i got confused.

Im starting with android (3 days ago) and i cant get the solution for what i want. So, i read a lot of threads here about asyncTask and now im sure i got confused.

First of all, this is my first question so i hope i get this at least right.

What i want is to have a class to connect to some server and the a result from it. After that analyses the json or xml.

so this is what i did. this is my activity class (called from main one)

    public class LogIn extends Activity implements OnClickListener {

    Button btn =null;

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.login);

    btn = (Button) findView开发者_如何学编程ById(R.id.btn_login);
    btn.setOnClickListener( this);
}   

public void onClick(View view) {
    HttpResponse response;
    Intent data = new Intent();
    //---get the EditText view---
    EditText txt_user = (EditText) findViewById(R.id.et_un);
    EditText txt_pwd =  (EditText) findViewById(R.id.et_pw);

    // aca tengo q llamar al conectar y chequear en BD
    ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
    postParameters.add(new BasicNameValuePair("usr", txt_user.getText().toString()));
    postParameters.add(new BasicNameValuePair("pass", txt_pwd.getText().toString()));
    String URL="whatever";
    try {
        response= new ConectServer(URL, postParameters).execute().get();

        LeerAutentificacionXml l= new LeerAutentificacionXml(response);
        String s=l.Transformar();
        data.setData(Uri.parse(s.toString()));
        setResult(RESULT_OK, data);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    //---set the data to pass back---
//  data.setData(Uri.parse(txt_user.getText().toString()+ " " + Uri.parse(txt_pwd.getText().toString())));
//  setResult(RESULT_OK, data);
    //---closes the activity---
    finish();
} }

and this is my class that connect to web services.

    public class ConectServer extends AsyncTask <Void, Void, HttpResponse> {

private String URL=null;
private ArrayList<NameValuePair> postParameters=null;
/** Single instance of our HttpClient */
private HttpClient mHttpClient;
/** The time it takes for our client to timeout */
public static final int HTTP_TIMEOUT = 30 * 1000;


  public ConectServer(String url, ArrayList<NameValuePair> p) {
      this.URL=url;
      this.postParameters=p;
  }

 private HttpClient getHttpClient() {
     if (mHttpClient == null) {
         mHttpClient = new DefaultHttpClient();
         final HttpParams params = mHttpClient.getParams();
         HttpConnectionParams.setConnectionTimeout(params, HTTP_TIMEOUT);
         HttpConnectionParams.setSoTimeout(params, HTTP_TIMEOUT);
         ConnManagerParams.setTimeout(params, HTTP_TIMEOUT);
     }
     return mHttpClient;
 }

 /**
 * Performs an HTTP Post request to the specified url with the
 * specified parameters.
 *
 * @param url The web address to post the request to
 * @param postParameters The parameters to send via the request
 * @return The result of the request
 * @throws Exception
 */
@Override
protected HttpResponse doInBackground(Void... params) {
    // TODO Auto-generated method stub
     HttpResponse response = null;
     try {
         HttpClient client = getHttpClient();
         HttpPost request = new HttpPost(this.URL);
         UrlEncodedFormEntity formEntity;
         formEntity = new UrlEncodedFormEntity(this.postParameters);
         request.setEntity(formEntity);
         response = client.execute(request);
     } catch (UnsupportedEncodingException e) {
         e.printStackTrace();
     } catch (ClientProtocolException e) {
        e.printStackTrace();
     } catch (IOException e) {
        e.printStackTrace();
    }

    return response;
}


public void onPreExecute() {
     super.onPreExecute();

}

protected void onPostExecute(HttpResponse response) {
     super.onPostExecute(response);
}}

I read about some design patter with listener but first i would like to understand better why this is not working. Im getting an error from server and i would like to know if this is correct or which big newby fail is going on.

Thx in advance.


Calling asyncTask.get() waits for the AsyncTask to finish and then returns the result. It basically defeats the purpose of the AsyncTask - the whole point of AsyncTask is that long-running task executes in the background thread and UI thread is not blocked during this time. When you call .get() it blocks the UI thread waiting for background thread to finish.

So, don't use get() and move ll actions that should happen when result is available to onPostExecute(..). Something like this:

protected void onPostExecute(HttpResponse response) {
    super.onPostExecute(response);
    LeerAutentificacionXml l= new LeerAutentificacionXml(response);
    String s=l.Transformar();
    data.setData(Uri.parse(s.toString()));
}

Of course, you will have to pass some references (data?) to AsyncTask (via constructor or otherwise).


Try to encapsulate all of your network code in the async task, so you can call it like this:

EditText txt_user = (EditText) findViewById(R.id.et_un);
EditText txt_pwd =  (EditText) findViewById(R.id.et_pw);
new LoginTask(txt_user.getText(), txt_pwd.getText(), this).execute();

with LoginTask being something like the following, based on the code in your question:

public class LoginTask extends AsyncTask<Void, Void, String> {

    // The URL probably won't change, so keep it in a static field
    private final static String URL = "http://....";

    private final String username;
    private final String password;
    private final Activity activity;

    /*
     * Pass all data required to log in and handle the result here.
     */
    public LoginTask(final String username, final String password, final Activity activity) {
        this.username = username;
        this.password = password;
        this.activity = activity;
    }

    /*
     * Do all the network IO and time-consuming parsing in here,
     * this method will be invoked in its own thread, not blocking the UI.
     */
    @Override
    protected String doInBackground(Void... params) {
        HttpClient client = getHttpClient();
        try {
            HttpEntity formEntity = new UrlEncodedFormEntity(Arrays.asList(
                    new BasicNameValuePair("usr", username),
                    new BasicNameValuePair("pass", password)));

            HttpPost request = new HttpPost(URL);
            request.setEntity(formEntity);

            HttpResponse response = client.execute(request);

            LeerAutentificacionXml l= new LeerAutentificacionXml(response);
            return l.Transformar();
        } catch (IOException ex) {
            // properly log your exception, don't just printStackTrace()
            // as you can't pinpoint the location and it might be cut off
            Log.e("LOGIN", "failed to log in", ex);
        } finally {
            client.getConnectionManager().shutdown();
        }
    }

    private HttpClient getHttpClient() {
        return null; // insert your previous code here
    }

    /*
     * This again runs on the UI thread, so only do here
     * what really needs to run on the UI thread.
     */
    @Override
    protected void onPostExecute(String response) {
        Intent data = new Intent();
        data.setData(Uri.parse(response));
        activity.setResult(Activity.RESULT_OK, data);
    }
}

Even if you don't think of the log in as being a "long-running task", anything involving network IO by definition is such a task as it might hang, time out, etc due to reasons beyond your control.

There's nothing wrong with having multiple classes that do network IO, as long as you carefully encapsulate the details like the above LoginTask example does. Try to write two, three AsyncTask classes of this type and then see if you can extract common parts into a common "web stuff" AsyncTask. Don't do it all at once, though.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号