0

私はかなり前からこれを自分で理解しようとしてきました..試行錯誤と研究によってですが、私はそれを理解することができないようです。私は非同期接続とネットワーク接続がかなり苦手なので、見過ごされているのは単純なことかもしれません。とにかく...関連するコードサンプルと説明を貼り付けます。

私の問題の簡単な背景。私は自分のアプリでRottenTomatoesAPIを使用しており、データの解析にGSONを使用しています。私は当初2.3をターゲットにしていましたが、これはうまくいきました。それから私はICSをサポートすることに決めました、そしてもちろん「UIスレッドでネットワーク操作がありません」に遭遇しました-それで私はAsyncTaskを掘り下げ始めました。

これが私のInputStreamメソッドです。

private InputStream retrieveStream(String url) {

    DefaultHttpClient client = new DefaultHttpClient();

    HttpGet getRequest = new HttpGet(url);

    try {

        HttpResponse getResponse = client.execute(getRequest);
        final int statusCode = getResponse.getStatusLine().getStatusCode();

        if (statusCode != HttpStatus.SC_OK) {
            Log.w(getClass().getSimpleName(),
                    "Error " + statusCode + " for URL " + url);
            return null;
        }

        HttpEntity getResponseEntity = getResponse.getEntity();
        return getResponseEntity.getContent();
    }
    catch (IOException e) {
        getRequest.abort();
        Log.w(getClass().getSimpleName(), "Error for URL " + url, e);
    }

    return null;
}

これは私のメインアクティビティで正常に機能していましたが、AsyncTaskに「変換」しようとすると問題が発生します。私はそれをこのように呼んでいます:

InputStream source = retrieveStream( url parameter );

次に、そのメソッドをAsyncTaskクラスに移動して、次のように呼び出してみました。

private PerformMovieSearch performSearch = new PerformMovieSearch(this);
InputStream source = performSearch.retrieveStream(movieQueryUrl);

しかし、それでも問題は解決しません。それでも、UIでのネットワークアクションの実行に関するエラーが発生します。私が理解する必要があるのは、私が推測するAsyncTaskから「retrieveStream」を呼び出す方法です。現在、そのクラスは次のようになっています。

package net.neonlotus.ucritic;

[imports]

public class PerformMovieSearch extends AsyncTask<String, Void, String> {

private final Context context;
private ProgressDialog progressDialog;


public PerformMovieSearch(Context context){
    this.context = context;
}


@Override
protected String doInBackground(String... urls) {
    retrieveStream(urls[0]);

    return null;

}

@Override
protected void onPreExecute() {
    progressDialog= ProgressDialog.show(context, "Please Wait","Searching movies", true);

}


@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    progressDialog.dismiss();

    MyActivity.mListAdapter.notifyDataSetChanged();
}

public InputStream retrieveStream(String url) {

    DefaultHttpClient client = new DefaultHttpClient();
    HttpGet getRequest = new HttpGet(url);

    try {
        HttpResponse getResponse = client.execute(getRequest);
        final int statusCode = getResponse.getStatusLine().getStatusCode();

        if (statusCode != HttpStatus.SC_OK) {
            Log.w(getClass().getSimpleName(),
                    "Error " + statusCode + " for URL " + url);
            return null;
        }

        HttpEntity getResponseEntity = getResponse.getEntity();
        return getResponseEntity.getContent();
    } catch (IOException e) {
        getRequest.abort();
        Log.w(getClass().getSimpleName(), "Error for URL " + url, e);
    }

    return null;
}

}

「doinbackground」は変更する必要があるものです...しかし、それを正しく機能させるための簡単な方法を見つけることができないようです。私はを使用して実行していました

new PerformMovieSearch(this).execute(movieQueryUrl);

それは多くのことであり、混乱を招く可能性があることを私は知っています...しかし、retrieveStreamメソッドを本質的に非同期で実行する方法を誰かが知っているなら、それは素晴らしいことです。私が言ったように、私は多くのことを試み、たくさんの研究をしましたが、有用なものを思い付くことができませんでした。

4

2 に答える 2

1

重要なのは、asynctaskがどのように機能するかを理解していなかったということです。

ガイドプロセスとスレッドを読む必要があります:http://developer.android.com/guide/components/processes-and-threads.html

しかし、わかりました、私はあなたを助けてみようと思います。

doInBackgroundでは、メソッドretrieveStreamを正しく呼び出していますが、ストリームには何もしていません。したがって、ストリームを処理してから返す必要があります。JSONを期待しているとおっしゃっていたように、文字列を受け取ると想定しているので、retrieveStreamのコードは次のようになります。

public String retrieveStream(String url) {

    DefaultHttpClient client = new DefaultHttpClient();
    HttpGet getRequest = new HttpGet(url);

    try {
        HttpResponse getResponse = client.execute(getRequest);
        final int statusCode = getResponse.getStatusLine().getStatusCode();

        if (statusCode != HttpStatus.SC_OK) {
            Log.w(getClass().getSimpleName(),
                    "Error " + statusCode + " for URL " + url);
            return null;
        }

        HttpEntity getResponseEntity = getResponse.getEntity();
        String jsonString = EntityUtils.toString(getResponseEntity);
        return jsonString;
    } catch (IOException e) {
        getRequest.abort();
        Log.w(getClass().getSimpleName(), "Error for URL " + url, e);
    }

    return null;
}

戻り値のタイプを文字列に変更したことを確認してください。また、名前をretrieveMoviesJSONなどに変更する必要があるかもしれません。

また、AsyncTaskを次のように変更する必要があります。

class PerformMovieSearch AsyncTask<String, Void, ArrayList<Movie>>() {

            @Override
            protected void onPreExecute() {
                progressDialog= ProgressDialog.show(context, "Please Wait","Searching movies", true);
            }

            @Override
            protected ArrayList<Movie> doInBackground(String... params) {
                String moviesJson = retrieveStream[params[0]];
                JSONObject moviesJson = new JSONObject(moviesJson);
                ArrayList<Movie> movies = new ArrayList<Movie>();
                /*
                 * Do your code to process the JSON and create an ArrayList of films.
                 * It's just a suggestion how to store the data.
                 */
                return movies;
            }

            protected void onPostExecute(ArrayList<Movie> result) {
                progressDialog.dismiss();
                //create a method to set an ArrayList in your adapter and set it here.
                MyActivity.mListAdapter.setMovies(result);
                MyActivity.mListAdapter.notifyDataSetChanged();
            }
        }

そして、あなたはあなたがしていたのと同じ方法で呼び出すことができます。

はっきりしていますか?さらに説明が必要ですか?

[] s Neto

于 2012-10-11T22:07:03.537 に答える
0

予想外の行動が見られます。コードをスキャンすると、おそらくコンパイルされて実行されているように見えますが、ListAdapterが新しいデータで更新されることはないと思います(つまり、結果をListViewまたはGridViewに表示しようとしているのに、何も表示されていません)。あれは正しいですか?それとも、メインスレッドでのネットワークエラーがまだ発生していますか?

HTTPクライアントを使用してデータを取得し、それを使用して何もしていません。これを解決する1つの方法は、次のようにコードを構造化することです
。1)AsyncTaskを拡張するクラスにListAdapterオブジェクトを受け取るコンストラクターがあります
。2)メインアクティビティがAsyncTaskのインスタンスを作成し、そのListAdapterオブジェクトへの参照を渡します。
3)doInBackgroundメソッドは、すべてのネットワークアクティビティを処理し、結果(Webサービスから取得したデータ)を返し、onPostExecuteメソッドに渡され
ます。4)onPostExecuteには、doInBackgroundから返されたデータが含まれます。 、コンストラクターで提供されたListAdapterがあるので、データを解析し、ListAdapterにデータを入力し、それを無効にしてリストが再描画されるようにします。

AsyncTaskを使用すると、onPreExecuteメソッドとonPostExecuteメソッドの両方でUIスレッドを操作できるため、画面に描画できるのはこれらの場所だけであることに注意してください(つまり、アダプターにデータを入力し、アダプターを無効にして再描画します)。

于 2012-10-11T22:08:45.907 に答える