如何使用单独的线程来执行http请求

时间:2022-10-13 13:23:46

I have an application that is performing HTTP Requests (specifically calling the FogBugz API) when the user clicks certain buttons. Right now, I am just creating a service when the application starts, and then calling different methods in that service to complete requests. However, when I do this, there is the usual hang in the UI thread. I have looked at AsyncTask, but am not sure it will do what I want to accomplish. Because I need to instantly parse the XML that the HTTP Request returns, I need to have a process that is able to return this data to the UI thread. Will ASyncTask be able to accomplish this, or is there some other way?

我有一个应用程序在用户单击某些按钮时执行HTTP请求(特别是调用FogBugz API)。现在,我只是在应用程序启动时创建服务,然后在该服务中调用不同的方法来完成请求。但是,当我这样做时,UI线程中通常会挂起。我看过AsyncTask,但我不确定它会做我想要完成的事情。因为我需要立即解析HTTP请求返回的XML,所以我需要一个能够将此数据返回给UI线程的进程。 ASyncTask能否实现这一目标,还是有其他方式?

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

This method is called by several others to perform HttpRequests. Once the inputstream is returned, the other methods parse for specific information.

其他几个人调用此方法来执行HttpRequests。返回输入流后,其他方法将解析特定信息。

2 个解决方案

#1


68  

The simplest way to do it would just be to do something like

最简单的方法就是做类似的事情

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

That will cause the code inside the run() method to execute in a new thread of execution. You can look into an async task if you like although I've personally never used it. This is a quick and simple way to get things done.

这将导致run()方法内的代码在新的执行线程中执行。如果您愿意,可以查看异步任务,尽管我个人从未使用它。这是完成工作的快速而简单的方法。

With regards to passing information back, I would use a Handler object which effectively allows you to set up a message queue for a given thread and pass messages to it which cause the execution of specific code. The reason you need to do this is because Android will not let any thread other than the UI thread update the actual UI.

关于传回信息,我将使用一个Handler对象,它有效地允许您为给定线程设置消息队列并将消息传递给它,从而导致执行特定代码。你需要这样做的原因是Android不会让除了UI线程之外的任何线程更新实际的UI。

Does that address your question? I know my first pass didn't fully address all of your issues.

这会解决你的问题吗?我知道我的第一次传球没有完全解决你的所有问题。

Edit Basically, what you do is define a handler object in your Activity like

编辑基本上,您所做的是在Activity中定义一个处理程序对象

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

    }

};

You also create static int constants that help tell the handler what to do. You basically use those to allow for several different types of messages to be passed to one instance of a handler. If there is only going to be one message that is passed back, then you don't have to worry about that.

您还可以创建静态int常量,以帮助告诉处理程序要执行的操作。您基本上使用它们来允许将几种不同类型的消息传递给处理程序的一个实例。如果只有一条消息会被传回,那么您不必担心这一点。

For example

private static final int UPDATE_UI = 1;

To send a message to the handler you call

要向您调用的处理程序发送消息

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

From the handler:

从处理程序:

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

};

Alternatively, where the inputStreamInstance is added to the Message object, you can pass any object you like so if you wanted to parse it into some kind of container object or something like that, you could do that as well. Just cast it back to that object from within the handler.

或者,在将inputStreamInstance添加到Message对象的位置,您可以传递任何您喜欢的对象,因此如果您想将其解析为某种容器对象或类似的东西,您也可以这样做。只需从处理程序中将其强制转换回该对象即可。

#2


5  

Try using AsyncTask. Goto this Link for more:

尝试使用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);
    }
}

Write the program for http request inside doinbackgroud()

在doinbackgroud()中写入http请求的程序

#1


68  

The simplest way to do it would just be to do something like

最简单的方法就是做类似的事情

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

That will cause the code inside the run() method to execute in a new thread of execution. You can look into an async task if you like although I've personally never used it. This is a quick and simple way to get things done.

这将导致run()方法内的代码在新的执行线程中执行。如果您愿意,可以查看异步任务,尽管我个人从未使用它。这是完成工作的快速而简单的方法。

With regards to passing information back, I would use a Handler object which effectively allows you to set up a message queue for a given thread and pass messages to it which cause the execution of specific code. The reason you need to do this is because Android will not let any thread other than the UI thread update the actual UI.

关于传回信息,我将使用一个Handler对象,它有效地允许您为给定线程设置消息队列并将消息传递给它,从而导致执行特定代码。你需要这样做的原因是Android不会让除了UI线程之外的任何线程更新实际的UI。

Does that address your question? I know my first pass didn't fully address all of your issues.

这会解决你的问题吗?我知道我的第一次传球没有完全解决你的所有问题。

Edit Basically, what you do is define a handler object in your Activity like

编辑基本上,您所做的是在Activity中定义一个处理程序对象

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

    }

};

You also create static int constants that help tell the handler what to do. You basically use those to allow for several different types of messages to be passed to one instance of a handler. If there is only going to be one message that is passed back, then you don't have to worry about that.

您还可以创建静态int常量,以帮助告诉处理程序要执行的操作。您基本上使用它们来允许将几种不同类型的消息传递给处理程序的一个实例。如果只有一条消息会被传回,那么您不必担心这一点。

For example

private static final int UPDATE_UI = 1;

To send a message to the handler you call

要向您调用的处理程序发送消息

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

From the handler:

从处理程序:

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

};

Alternatively, where the inputStreamInstance is added to the Message object, you can pass any object you like so if you wanted to parse it into some kind of container object or something like that, you could do that as well. Just cast it back to that object from within the handler.

或者,在将inputStreamInstance添加到Message对象的位置,您可以传递任何您喜欢的对象,因此如果您想将其解析为某种容器对象或类似的东西,您也可以这样做。只需从处理程序中将其强制转换回该对象即可。

#2


5  

Try using AsyncTask. Goto this Link for more:

尝试使用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);
    }
}

Write the program for http request inside doinbackgroud()

在doinbackgroud()中写入http请求的程序