Android, как я могу инкапсулировать класс AsyncTask с сетевыми подключениями - PullRequest
1 голос
/ 27 сентября 2011

Я начинаю с Android (3 дня назад), и я не могу получить решение для того, что я хочу.Итак, я прочитал здесь много веток об asyncTask, и теперь я уверен, что я запутался.

Прежде всего, это мой первый вопрос, поэтому я надеюсь, что по крайней мере это правильно.

То, что я хочу, это иметь класс для подключения к какому-либо серверу и результат от него.После этого анализирует JSON или XML.

, так что это то, что я сделал.это мой класс активности (вызывается из основного)

    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) findViewById(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();
} }

, и это мой класс, который подключается к веб-сервисам.

    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);
}}

Я читал о каком-то шаблоне проектирования со слушателем, но сначалаЯ хотел бы лучше понять, почему это не работает.Я получаю сообщение об ошибке от сервера, и я хотел бы знать, правильно ли это, или какой большой новый сбой происходит.

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 27 сентября 2011

Вызов asyncTask.get() ожидает завершения AsyncTask, а затем возвращает результат.По сути, это не соответствует цели AsyncTask - весь смысл AsyncTask в том, что долго выполняющаяся задача выполняется в фоновом потоке, и поток пользовательского интерфейса не блокируется в течение этого времени.Когда вы вызываете .get(), он блокирует поток пользовательского интерфейса, ожидающий завершения фонового потока.

Поэтому не используйте get() и перемещайте все действия, которые должны произойти, когда результат доступен для onPostExecute(..).Примерно так:

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

Конечно, вам придется передать некоторые ссылки (data?) На AsyncTask (через конструктор или иным образом).

1 голос
/ 27 сентября 2011

Попробуйте инкапсулировать весь вашего сетевого кода в асинхронную задачу, чтобы вы могли назвать его так:

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();

с LoginTask, что-то вроде следующего, на основена код в вашем вопросе:

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);
    }
}

Даже если вы не думаете о входе в систему как о «длительной задаче», все, что связано с сетевым вводом-выводом по определению, является такой задачей, которая можетзависание, время ожидания и т. д. по независящим от вас причинам.

Нет ничего плохого в наличии нескольких классов, которые выполняют сетевой ввод-вывод, если вы тщательно инкапсулируете детали, как в приведенном выше примере LoginTask.Попробуйте написать два, три AsyncTask класса этого типа, а затем посмотрите, сможете ли вы извлечь общие части в общий «материал сети» AsyncTask.Не делай все это одновременно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...