Как использовать отдельный поток для выполнения HTTP-запросов

У меня есть приложение, которое выполняет HTTP-запросы (в частности, вызывая API FogBugz), когда пользователь нажимает определенные кнопки. Прямо сейчас, я просто создаю службу, когда приложение запускается, а затем вызывает разные методы в этой службе для завершения запросов. Однако, когда я это делаю, обычно наблюдается зависание в потоке пользовательского интерфейса. Я посмотрел на AsyncTask, но не уверен, что он сделает то, что я хочу выполнить. Поскольку мне нужно мгновенно разобрать XML-запрос, возвращаемый HTTP-запросом, мне нужен процесс, который сможет вернуть эти данные в поток пользовательского интерфейса. Удастся ли ASyncTask выполнить это, или есть какой-то другой способ?

    public static InputStream makeRequest(String httpRequest)
    {
        In a separate thread, run HTTP Request, get back and process, return inputstream
    }

Этот метод вызывается несколькими другими для выполнения HttpRequests. После возвращения входного потока другие методы анализируют конкретную информацию.

Ответ 1

Самый простой способ сделать это - просто сделать что-то вроде

//Body of your click handler
Thread thread = new Thread(new Runnable(){
  @Override
  public void run(){
    //code to do the HTTP request
  }
});
thread.start();

Это приведет к тому, что код внутри метода run() будет выполняться в новом потоке выполнения. Вы можете посмотреть асинхронную задачу, если хотите, хотя я лично ее никогда не использовал. Это быстрый и простой способ добиться результата.

Что касается передачи информации назад, я бы использовал объект Handler, который эффективно позволяет настроить очередь сообщений для данного потока и передавать ему сообщения, которые вызывают выполнение определенного кода. Причина, по которой вам нужно это сделать, - это то, что Android не позволит никому, кроме потока пользовательского интерфейса, обновлять фактический пользовательский интерфейс.

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

Изменить В основном, что вы делаете, это определить объект-обработчик в Activity как

private Handler handler_ = new Handler(){
    @Override
    public void handleMessage(Message msg){

    }

};

Вы также создаете статические константы int, которые помогают сообщать обработчику, что делать. В основном вы используете те, которые позволяют передавать несколько разных типов сообщений одному экземпляру обработчика. Если будет только одно сообщение, которое будет передано обратно, вам не придется беспокоиться об этом.

Например

private static final int UPDATE_UI = 1;

Чтобы отправить сообщение обработчику, вызываемому

handler_.sendMessage(Message.obtain(handler_, UPDATE_UI, inputStreamInstance));

От обработчика:

private Handler handler_ = new Handler(){
    @Override
public void handleMessage(Message msg){
    switch(msg.what){
            case UPDATE_UI:
            InputStream is = (InputStream)msg.obj;
            //do what you need to with the InputStream
            break;
        }
    }

};

В качестве альтернативы, когда inputStreamInstance добавляется к объекту Message, вы можете передать любой объект, который вам нравится, если вы хотите разобрать его на какой-то контейнерный объект или что-то в этом роде, вы тоже можете это сделать. Просто верните его обратно к этому объекту из обработчика.

Ответ 2

Попробуйте использовать AsyncTask. Перейти к этой Ссылка для получения дополнительной информации:

private class SyncIncoData extends AsyncTask<String, String, String> {
    ProgressBar pb;
    ProgressBar pbar;

    @Override
    protected String doInBackground(String... urls) {
        for (int i = 0; i <= 100; i++) {
            publishProgress(i);
        }
        return null;
    }

    @Override
    protected void onPreExecute() {

        super.onPreExecute();

        pb = (ProgressBar) findViewById(R.id.progressBarsync4);
        pb.setVisibility(View.VISIBLE);

    }

    @Override
    protected void onPostExecute(String result) {

        pb = (ProgressBar) findViewById(R.id.progressBarsync4);
        pb.setVisibility(View.INVISIBLE);

    }

    @Override
    protected void onProgressUpdate(String... values) {
        pbar = (ProgressBar) findViewById(R.id.progressBarpbar);
        pbar.setProgress(Integer.parseInt(values[0]));
        super.onProgressUpdate(values);
    }
}

Напишите программу для http-запроса внутри doinbackgroud()