【问题标题】:Android Chat with Long Polling带有长轮询的 Android 聊天
【发布时间】:2017-04-11 16:10:48
【问题描述】:

我在 Android 应用程序中使用长轮询实现聊天应用程序时遇到问题。新消息的搜索工作正常,它在 HttpUrlConnection 的异步任务中运行。问题在于发送消息。我也使用了另一个异步任务HttpUrlConnection,但根据我一直在打印的日志,消息仅在搜索新消息完成时发送,即在 30 秒的长轮询之后。 这是我正在使用的异步测试:

HttpPost.java

package com.roscosoft.taxifast;

import android.os.AsyncTask;
import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

/**
 * Created by titin on 7/12/16.
 */

public class HttpPost extends AsyncTask<Void, Void, Boolean> {
Exception error;

public interface HttpPostInterface {
    void termino(JSONObject obj);
    void cancelo(String error);
}


public static String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
    StringBuilder result = new StringBuilder();
    boolean first = true;
    for(Map.Entry<String, String> entry : params.entrySet()){
        if (first)
            first = false;
        else
            result.append("&");

        result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
        result.append("=");
        result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
    }

    return result.toString();
}

private StringBuilder response;
private String postDataString;
private String url;
private HttpPostInterface delegate;
private int timeout;

HttpPost(String urlx, String postDataStringx, HttpPostInterface del) {
    url = urlx;
    postDataString = postDataStringx;
    delegate = del;
    timeout = 30000;
}
HttpPost(String urlx, String postDataStringx, HttpPostInterface del, int timeoutx) {
    url = urlx;
    postDataString = postDataStringx;
    delegate = del;
    timeout = timeoutx;
}


@Override
protected Boolean doInBackground(Void... params) {
    response = new StringBuilder();
    URL urlc = null;
    HttpURLConnection con = null;
    try{
        urlc = new URL(url);
    }catch (MalformedURLException e){
        Log.i("rosco", e.getMessage());
        error = e;
        return false;
    }
    try {
        con = (HttpURLConnection)urlc.openConnection();
        con.setReadTimeout(timeout);
        con.setConnectTimeout(timeout);
        con.setRequestMethod("POST");
        con.setDoInput(true);
        con.setDoOutput(true);

        OutputStream os = con.getOutputStream();
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
        writer.write(postDataString);

        writer.flush();
        writer.close();
        os.close();

        int responseCode = con.getResponseCode();
        if (responseCode == HttpsURLConnection.HTTP_OK){
            String line;
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            while ((line = br.readLine()) != null){
                response.append(line);
            }
        }else{
            error = new Exception("Error:"+responseCode);
            return false;
        }
    } catch (Exception e) {
        Log.i("rosco", "Hubo un error al hacer el request:"+e.getMessage());
        error = e;
        return false;
    }finally {
        con.disconnect();
    }
    return true;
}

@Override
protected void onPostExecute(final Boolean success) {

    if (success) {
        try{
            if (response.toString().length() == 0){
                if(delegate != null) delegate.cancelo("No hay respuesta del servidor");
            }else{
                //Log.i("rosco", response.toString()); // solo en desarrollo
            }
            JSONObject obj = new JSONObject(response.toString());
            if(delegate != null) delegate.termino(obj);
        }catch (JSONException e){
            Log.i("rosco", "Json malformado:"+e.getMessage()+":\n"+response.toString());
            if(delegate != null) delegate.cancelo(response.toString());
        }
    } else {
        if(delegate != null) delegate.cancelo(error.getMessage());
    }
}

@Override
protected void onCancelled() {
    if(delegate != null) {
        if (error == null)
            delegate.cancelo("Se cancelo el request");
        else
            delegate.cancelo(error.getMessage());
    }
}
}

Web 服务是用 PHP 制作的,服务器是否有可能等待第一个连接完成以接受“发送消息”连接? 如果是这样,您知道如何解决吗? 提前非常感谢。

【问题讨论】:

  • 如果没有关于服务器实现的更多信息,这可能无法回答。

标签: java php android


【解决方案1】:

您需要使用THREAD_POOL_EXECUTOR 来执行AsyncTask。默认实现使用在单个线程上运行的串行执行器

new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

【讨论】:

    【解决方案2】:

    所有 AsyncTask 都在单线程中执行序列。虽然第一个 AsyncTask 没有完成,但第二个任务不会启动。我(和很多开发人员)不推荐使用 AsyncTask。 替代方案:Java 线程、Rx、来自 java.util.concurrent 的 Executors 等。 或者使用 Square 的 Retrofit 库来执行异步 http 请求。

    【讨论】:

    • 谢谢,这就是问题所在:)
    猜你喜欢
    • 2013-03-28
    • 2012-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    • 2012-11-06
    • 2013-08-14
    • 1970-01-01
    相关资源
    最近更新 更多