Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/192.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在自己的线程中执行web请求?_Java_Android_Multithreading - Fatal编程技术网

Java 如何在自己的线程中执行web请求?

Java 如何在自己的线程中执行web请求?,java,android,multithreading,Java,Android,Multithreading,我正在创建一个android应用程序,它必须在后台执行web请求,然后处理接收到的数据,并根据服务器响应修改用户界面 在后台发布请求和处理数据的目的是避免冻结用户界面。然而,目前我注意到用户界面冻结,所以我不确定逻辑是否正常工作 下面是代码的一部分,它应该在自己的线程中发布请求和处理响应,然后将数据传递给GUI: public class ServerConnection { Queue<String> requests; ... DefaultHttpClient httpC

我正在创建一个android应用程序,它必须在后台执行web请求,然后处理接收到的数据,并根据服务器响应修改用户界面

在后台发布请求和处理数据的目的是避免冻结用户界面。然而,目前我注意到用户界面冻结,所以我不确定逻辑是否正常工作

下面是代码的一部分,它应该在自己的线程中发布请求和处理响应,然后将数据传递给GUI:

public class ServerConnection {

Queue<String> requests;

...

DefaultHttpClient httpClient;
HttpHost targetHost;

Handler handler;

ServerResponseHandler responseHandler;
Activity activity;

public ServerConnection(Activity activity){
    this.activity = activity;
    this.responseHandler = (ServerResponseHandler) activity;
    httpClient = new DefaultHttpClient();
    targetHost = new HttpHost(TARGET_DOMAIN, 80, "http");
    requests = new LinkedList<String>();
}



private Runnable requestSender = new Runnable(){

    @Override
    public void run() {
        if(!requests.isEmpty()){
            String requestString = requests.remove();
            HttpGet httpGet = new HttpGet(requestString);
            httpGet.addHeader("Accept", "text/xml");
            String encodingString = "testuser:testpass";
            String sEncodedString = Base64Coder.encodeString(encodingString);

            try{

                String sContent = fetchURL(requestString, sEncodedString);

                XMLParser xmlParser = new XMLParser();

                List <Product> products = xmlParser.getProducts(sContent);

                responseHandler.onProductsResponse(products);
            }
            catch(Exception ex){
                Log.e(TAG, ex.getMessage());
            }
        }
    }
};

public void sendRequest(String requestString){
    requests.add(requestString);
    handler = new Handler();
    handler.post(requestSender);
}
公共类服务器连接{
排队请求;
...
默认httpClient httpClient;
HttpHost-targetHost;
处理者;
ServerResponseHandler-responseHandler;
活动;
公共服务器连接(活动){
这个。活动=活动;
this.responseHandler=(ServerResponseHandler)活动;
httpClient=新的DefaultHttpClient();
targetHost=新的HttpHost(TARGET_域,80,“http”);
请求=新建LinkedList();
}
private Runnable requestSender=new Runnable(){
@凌驾
公开募捐{
如果(!requests.isEmpty()){
String requestString=requests.remove();
HttpGet HttpGet=新的HttpGet(请求字符串);
addHeader(“Accept”、“text/xml”);
String encodingString=“testuser:testpass”;
String sEncodedString=Base64Coder.encodeString(encodingString);
试一试{
String scocontent=fetchURL(requestString,sEncodedString);
XMLParser XMLParser=新的XMLParser();
List products=xmlParser.getProducts(scocontent);
负责人对产品的响应(产品);
}
捕获(例外情况除外){
Log.e(标记,例如getMessage());
}
}
}
};
公共void sendRequest(字符串requestString){
add(requestString);
handler=新的handler();
handler.post(requestSender);
}
方法sendRequest()是从实现ServerResponseHandler的主活动调用的

负责人对产品的响应(产品)


产品列表(来自web的数据)已传递到主活动。无论如何,由于性能不佳,如果有人能够纠正上述逻辑中的任何可能问题或建议任何其他(更好)选项,我将不胜感激。

我建议您看看(自Android 1.5起提供)

它简化了创建后台线程的过程,该线程一旦完成就与GUI线程同步

您应该能够使用下面列出的代码实现您正在尝试的功能

private class DownloadFilesTask extends AsyncTask<String, List<Product>, Integer> {
     protected List<Products> doInBackground(String... requestStrings) {
        int count = requestStrings.length;
        int results = 0;
        for (int i = 0; i < count; i++) {
          String requestString = requestStrings[i];
          HttpGet httpGet = new HttpGet(requestString);
          httpGet.addHeader("Accept", "text/xml");
          String encodingString = "testuser:testpass";
          String sEncodedString = Base64Coder.encodeString(encodingString);
          try{
            String sContent = fetchURL(requestString, sEncodedString);
            XMLParser xmlParser = new XMLParser();
            List <Product> products = xmlParser.getProducts(sContent);
            results++;
            publishProgress(products);
          }
          catch(Exception ex){
            Log.e(TAG, ex.getMessage());
          }
        }
        return results;
     }

     protected void onProgressUpdate(Integer... progress) {
         // TODO You are on the GUI thread, and the first element in 
         // the progress parameter contains the last progress
         // published from doInBackground, so update your GUI
     }

     protected void onPostExecute(int result) {
       // Processing is complete, result contains the number of 
       // results you processed
     }
 }
根据,我认为
post()
方法不会创建任何线程。如果我是对的,它会在处理程序所连接的线程上执行
Runnable
。因此,在这种情况下,这是活动线程,所以是UI线程!这就是性能差的原因

您必须实现一个
线程
,该线程执行您的
可运行
。但这样做,您将无法通过调用以下命令来更新您的活动:

responseHandler.onProductsResponse(products);
这是因为您不再在UI线程中,只有UI线程被授权与UI交互(因此活动)。 因此,您必须通过访问
处理程序来替换此调用

Message msg = handler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putSerializable( "products", products ); //not sure it will pass here 
msg.setData( bundle );
handler.sendMessage( msg );
并为
处理程序实现
handleMessage()
方法:

@Override
public void handleMessage( Message msg )
{
  List <Product> products = msg.getData().getSerializable( "products" );
  responseHandler.onProductsResponse(products);
}
@覆盖
公共无效handleMessage(消息消息消息)
{
列出产品=msg.getData().getSerializable(“产品”);
负责人对产品的响应(产品);
}
最后但并非最不重要的一点:仍然必须在活动线程中创建
处理程序

@Override
public void handleMessage( Message msg )
{
  List <Product> products = msg.getData().getSerializable( "products" );
  responseHandler.onProductsResponse(products);
}