1

私の ListView は Web サーバーからデータを取得します。

最初に 10 個のアイテムがフェッチされ、後で onScroll でさらに 10 個、というようにフェッチされます。

これは 4 ~ 5 回のスクロールでは正常に機能しますが、後で次の例外が発生します。

java.net.SocketException: Socket closed.

この後:

E/OSNetworkSystem(27034): JNI EX in read

また、 Socket closedの代わりに、次の例外が発生することもあります。

java.io.IOException: Attempted read on closed stream

次に、10 個の新しいアイテムを追加する代わりに、以前に取得した 10 個のアイテムを追加します。これは、例外のために、アダプターで使用される ArrayList の項目を置き換えていないためです。

この例外の原因は何ですか?

編集:

最初の 3 ~ 5 回のスクロールでは問題なく動作し、この例外のために間違ったデータ (前のデータ) が返されます。スクロールを続けると、後で問題なく動作し、後でランダムに例外が返されます。

リスト アイテムを取得するコード:

postData を使用して Web サーバーからデータを取得します

public static String PostData(String url, String sa[][]) {

        DefaultHttpClient client = getThreadSafeClient();
        ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        int n = sa.length;
        for (int i = 0; i < n; i++) {
            nameValuePairs.add(new BasicNameValuePair(sa[i][0], sa[i][1]));
            Log.d(sa[i][0], "" + sa[i][1]);
        }
        HttpPost httppost;
        try {
            httppost = new HttpPost(baseUrl + url);
        } catch (Exception e) {
        }
        try {
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        } catch (UnsupportedEncodingException e) {
        }
        HttpResponse response = null;
        try {
            response = client.execute(httppost);
        } catch (ClientProtocolException e) {
        } catch (IOException e) {
        } catch (Exception e) {
        }
        HttpEntity entity = response.getEntity();
        try {
            is = entity.getContent();
        } catch (IllegalStateException e) {
        } catch (IOException e) {
        }
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, "iso-8859-1"), 8);
            sb = new StringBuilder();
            sb.append(reader.readLine());
            String line = "0";
            while ((line = reader.readLine()) != null) {
                sb.append("\n" + line);
            }
            is.close();
            result = sb.toString();
        } catch (Exception e) {
        }
        return result;
    }

PostData で使用している ThreadSafeClient

    public static DefaultHttpClient getThreadSafeClient() {

    DefaultHttpClient client = new DefaultHttpClient();
    ClientConnectionManager mgr = client.getConnectionManager();
    HttpParams params = client.getParams();
    client = new DefaultHttpClient(new ThreadSafeClientConnManager(params,
            mgr.getSchemeRegistry()), params);
    return client;
}

アクティビティの AsyncTask で、新しいデータ onScroll を取得します。これは onScroll で呼び出されます

AsyncTask{

ArrayList<item> itemList = new Arraylist<item>();
doInBackground(){

    String response = PostData(url, sa);
    //sa has namevaluepairs as a 2-dimensional array
    JSONArray JArray = new JSONArray(response);
    for(int i = 0; i < jArray.length; i++){

        itemList.add(convertToItem(JArrya.getJSONObject("items")));
    }
}
onPostExecute(){

    for(int i = 0; i < itemList.size(); i++){
        mListAdapter.add(itemList.get(i));
    }
    mListAdapter.notifyDataSetChanged();
}
}

長いコードなので、重要な行だけを貼り付けます

どんな助けでも感謝します。

編集:

PostDataメソッドをこれに変更した後、正常に動作しました。

public static String PostData(String url, String sa[][]) {

    ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
    int n = sa.length;
    for (int i = 0; i < n; i++) {
        nameValuePairs.add(new BasicNameValuePair(sa[i][0], sa[i][1]));
    }
    HttpPost httppost;
    httppost = new HttpPost(baseUrl + url);
    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

    HttpResponse response = null;
    response = client.execute(httppost);
    HttpEntity entity = response.getEntity();
    String res = EntityUtils.toString(entity);
    return res;
}

では、前のケースでは is(InputStream)sb(Stringbuilder)ローカル変数ではないためでしょうか?

ありがとうございました

4

2 に答える 2

1

PostData()メソッドで定義されていない 2 つのオブジェクトを使用しているため、メソッドはスレッド セーフではありません。

is = entity.getContent();
sb = new StringBuilder();

これにより、実行中の他のスレッドからのソケットが次のように閉じられます。

is.close();

両方をメソッドにローカルに定義すると、問題が解決するはずです。

よろしく。

于 2012-11-24T15:20:38.730 に答える
1

On scroll は、ListView の y 座標が変更されるたびに呼び出されるため、リストがスクロールされているときにサーバーに多くの接続を行っている可能性があり、例外が発生する可能性があります。

これはあなたを助けるかもしれません: http://benjii.me/2010/08/endless-scrolling-listview-in-android/

于 2012-11-22T14:39:44.230 に答える