2

私はAndroidを初めて使用します。URLのコンテンツをダウンロードしているAsyncTaskがあります。AsyncTaskがUIを直接操作して、再利用可能なコードの一部として持つことを望まなかったので、それを独自のファイルに入れて、文字列を返しました。問題は、AsyncTaskが終了する前に戻りが発生することです(.excecute()の.get()を使用している場合でも)。そのため、何も返されません。これが私が今持っているものです:

package com.example.mypackage;

import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutionException;

import android.os.AsyncTask;

public class URLContent {
private String content = "default value";

public String getContent(String URL){
    try {
        new getAsyncContent().execute(URL).get();
    } catch (InterruptedException e) {
        content = e.getMessage();
    } catch (ExecutionException e) {
        content = e.getMessage();
    }
    return content;
}

private class getAsyncContent extends AsyncTask<String, Integer, String>
{
    @Override
    protected void onPostExecute(String result) {
         content = result;
    }

    @Override
    protected String doInBackground(String... urls) {
        try{
            return URLResponse(urls[0]);
        } catch (Exception e){
            return e.getMessage();
        }

    }
}

private String IStoString(InputStream stream) throws IOException, UnsupportedEncodingException {
    try {
        return new java.util.Scanner(stream, "UTF-8").useDelimiter("\\A").next();
    } catch (java.util.NoSuchElementException e) {
        return "";
    }
}

private String URLResponse(String URLToget) throws IOException {
    InputStream is = null;

    try {
        URL url = new URL(URLToget);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(10000 /* milliseconds */);
        conn.setConnectTimeout(15000 /* milliseconds */);
        conn.setRequestMethod("GET");
        conn.setDoInput(true);
        conn.connect();
        is = conn.getInputStream();
        // Convert the InputStream into a string
        String contentAsString = IStoString(is);
        return contentAsString;
    } finally {
        if (is != null) {
            is.close();
        } 
    }
}
}

私のメインスレッドがどういうわけか結果を取り戻すようにそれを解決するための最良の方法は何でしょうか?イベントとコールバックについて言及している記事に出くわしました。それが最善の方法ですか..?

4

4 に答える 4

2

しないでくださいget()doInBackgroundメソッド内で URL 実行の結果を処理するロジックを用意するだけです。何も返す必要はありません。あなたの特定のケースでは、結果が配信される前に get() がすぐに実行されるという問題があります

これは非同期実行であり、線形ロジックを適用することはできません

于 2012-09-21T17:28:18.943 に答える
2

ご助力いただきありがとうございます。Alex による asyncTask クラスを拡張するためのソリューションを試してみます。クリーンなソリューションのように思えます。

AsyncTask を持つクラスのインターフェイスを使用し、メイン クラスにイベント リスナーを追加することで、私がしようとしていたことをなんとか実行できました。したがって、コンテンツを取得するクラスは次のようになります。

package com.example.test;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;

import android.os.AsyncTask;

public class URLContent {
public void getContent(String URL){
    new getAsyncContent().execute(URL);
}

public interface OnContentDownloadedListener{
    public abstract void onContentDownloaded(String content);
}
private OnContentDownloadedListener contentDownloadedListener = null;
public void setOnContentDownloadedListener(OnContentDownloadedListener content){
    contentDownloadedListener = content;
}

private class getAsyncContent extends AsyncTask<String, Integer, String>
{
    @Override
    protected void onPostExecute(String result) {
        contentDownloadedListener.onContentDownloaded(result);
    }

    @Override
    protected String doInBackground(String... urls) {
        try{
            return URLResponse(urls[0]);
        } catch (Exception e){
            return e.getMessage();
        }
    }
}

private String IStoString(InputStream stream) throws IOException, UnsupportedEncodingException {
    try {
        return new java.util.Scanner(stream, "UTF-8").useDelimiter("\\A").next();
    } catch (java.util.NoSuchElementException e) {
        return "";
    }
}

private String URLResponse(String URLToget) throws IOException {
    InputStream is = null;

    try {
        URL url = new URL(URLToget);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(10000 /* milliseconds */);
        conn.setConnectTimeout(15000 /* milliseconds */);
        conn.setRequestMethod("GET");
        conn.setDoInput(true);
        conn.connect();
        is = conn.getInputStream();
        // Convert the InputStream into a string
        String contentAsString = IStoString(is);
        return contentAsString;
    } finally {
        if (is != null) {
            is.close();
        } 
    }
}
}

そして、私のメイン クラスには、UI の更新を処理するイベント リスナーがあります。

urlContent.setOnContentDownloadedListener(new URLContent.OnContentDownloadedListener(){
            public void onContentDownloaded(String content){
//update UI or do something with the data
}
于 2012-09-22T14:23:34.437 に答える
1

onPostExecute() の主な目的は、AsyncTask の結果で UI を更新することです。実装と UI での使用方法を別々に保つために、Activity で getAsyncContent クラスを拡張し、onPostExecute() メソッドをオーバーライドできます。このメソッドは UI スレッドで実行されます。

于 2012-09-21T17:29:17.193 に答える
1

非同期タスクから UI を更新する必要がない場合は、単純なスレッドを作成して実行します。完了したら、ブロードキャストを送信するだけです。

new Thread(new Runnable() {
    @Override
    public void run() {
        // Do the download here...
        ....
        // 
        sendBroadcast(some_intent);
}).start();
于 2012-09-21T17:43:37.997 に答える