6

コードや構造の何が問題なのかよくわかりません。AsyncTask を使用して画像をダウンロードし、その間に進行状況バーを表示したいと考えていました。しかし、私はそれを行ういくつかの異なる方法を試しました。それでも失敗し、何が問題なのかわかりません。私の構造の流れは

ContentID は、画像のコンテンツ ID を格納する文字列配列です。

主な問題: URL から画像をダウンロードして電話に保存することはできましたが、ダウンロードした画像はすべて同じ画像です。それは異なるイメージであるべきです、それは私が期待したものではありません.

二次的な問題: アプリケーションが画像をダウンロードしている間、進行状況バーがポップアップしますが、進行状況バーは進行状況を更新しませんでした。0% のままで、ダウンロードが完了すると消えます。

私が述べたように、一次および二次の問題の原因を知りたかったのです。私のコードの何が問題なのかわかるかもしれない場合は、コメントまたは回答を残してください。どんな助けでも大歓迎です。

if(isSyncSuccess){

     SetConstant.IMAGE_EXIST = 1;
     pDialog = new ProgressDialog(GalleryScreen.this);
     pDialog.setMessage("Downloading file. Please wait...");
     pDialog.setIndeterminate(false);
     pDialog.setProgress(0);
     pDialog.setMax(contentId.length);
     pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
     pDialog.setCancelable(true);


     if (contentId.length>0){
     Log.i(TAG, "contentid.length:" +contentId.length);
         for (int i=0;i<contentId.length;i++){
             if(helper.databaseChecking(useremail, contentId[i])){
                 contentdownload = i;
                 SetConstant.CONTENT_ID = contentId[i]; 

                 String URL = SetConstant.URL_DOWNLOAD_CONTENT+contentId[i];

                 DownloadFile downloadFile = new DownloadFile();
                 downloadFile.execute(URL);


                 }



    private class DownloadFile extends AsyncTask<String, Integer, String>{
    @Override
    protected String doInBackground(String... sUrl){
                Bitmap bm;
                InputStream in;

        try{

            in = new java.net.URL(sUrl[0]).openStream();
            bm = BitmapFactory.decodeStream(new PatchInputStream(in));
            File storage = new File(Environment.getExternalStorageDirectory() + File.separator + "/Image/");
            Log.i(TAG,"storage:" +storage);
            Log.i(TAG,"storage:" +storage.getAbsolutePath());
            if(!storage.exists()){
                storage.mkdirs();

            }
                String FileName = "/"+SetConstant.CONTENT_ID+".jpg"; 
                FileOutputStream fos = new FileOutputStream(storage + FileName);
                bm.compress(Bitmap.CompressFormat.JPEG, 85, fos);

                String filepath = storage + FileName;
                File filecheck = new File (filepath);
                long fileSize = filecheck.length();
                fos.flush();
                fos.close();

                Log.i(TAG, "bm:" +bm);
                Log.i(TAG, "fos:" +fos);
                Log.i(TAG, "filesize:" +fileSize);
                Log.i(TAG, "filepath:" +filepath);


        }
        catch(IOException e1){
                e1.printStackTrace();
                }   

        return null;
    }

    @Override
    protected void onPreExecute(){
        super.onPreExecute();
        pDialog.show();
    }

    @Override
    protected void onProgressUpdate(Integer... progress){
        super.onProgressUpdate(progress);
        pDialog.setProgress(progress[0]);
    }

    protected void onPostExecute(String result){
        super.onPostExecute(result);
        pDialog.dismiss();
    }
}

編集

これで、アプリケーションが画像をダウンロードできるようになり、プログレス バーも機能するようになりました。しかし、別の問題は、アプリケーションがダウンロードを完了できなかったときにエラー メッセージを返す方法です。現在、アプリケーションのダウンロードに失敗すると、アプリケーションがクラッシュします。doInBackground 側で実行するべきではないと考えていました。しかし、他にどこでチェックを行うことができますか? アプリケーションをクラッシュさせる代わりに、エラー メッセージとして返して、ユーザーに再試行を要求する方法はありますか?

4

4 に答える 4

5

onProgressUpdate中に電話したことはありませんdoInBackGround(...)。のインスタンスを複数実行することAsyncTaskはお勧めできません。これが私が提案するものです:

if(isSyncSuccess){
    SetConstant.IMAGE_EXIST=1;
    pDialog=new ProgressDialog(GalleryScreen.this);
    pDialog.setMessage("Downloading file. Please wait...");
    pDialog.setIndeterminate(false);
    pDialog.setProgress(0);
    pDialog.setMax(contentId.length);
    pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    pDialog.setCancelable(true);

    new DownloadFile().execute();
}

private class DownloadFiles extends AsyncTask<String, Integer, String> {
    @Override
    protected String doInBackground(String... sUrl) {
        Bitmap bm;
        InputStream in;

        if (contentId.length > 0) {
            for (int i = 0; i < contentId.length; i++) {
                if (helper.databaseChecking(useremail, contentId[i])) {
                    contentdownload = i;
                    SetConstant.CONTENT_ID = contentId[i];

                    String URL = SetConstant.URL_DOWNLOAD_CONTENT + contentId[i];
                    //YOUR INTRESTING LOOP HERE.
                    publishProgress(30);
                    //SOME INTRESTING NUMBER FOR PROGRESS UPDATE
                }
            }

            try {
                in = new java.net.URL(sUrl[0]).openStream();
                bm = BitmapFactory.decodeStream(new PatchInputStream(in));
                File storage = new File(Environment.getExternalStorageDirectory() + File.separator + "/Image/");
                Log.i(TAG, "storage:" + storage);
                Log.i(TAG, "storage:" + storage.getAbsolutePath());
                if (!storage.exists()) {
                    storage.mkdirs();

                }
                String FileName = "/" + SetConstant.CONTENT_ID + ".jpg";
                FileOutputStream fos = new FileOutputStream(storage + FileName);
                bm.compress(Bitmap.CompressFormat.JPEG, 85, fos);

                String filepath = storage + FileName;
                File filecheck = new File(filepath);
                long fileSize = filecheck.length();
                fos.flush();
                fos.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPreExecute () {
            super.onPreExecute();
            pDialog.show();
        }

        @Override
        protected void onProgressUpdate (Integer...progress){
            super.onProgressUpdate(progress);
            pDialog.setProgress(progress[0]);
        }

        protected void onPostExecute (String result){
            super.onPostExecute(result);
            pDialog.dismiss();
        }
    }
}

もちろん、このコードは実行されず、スコープを修正する必要があります。しかし、私が提案しようとしているのは、ループが にある必要があるということです。この場合、特定の時間にdoInBackGround(...)のインスタンスを 1 つだけ持つ必要があり、 .AsyncTaskonProgressUpdate()

于 2012-12-21T02:46:25.777 に答える
2

主な問題:

SetConstant.CONTENT_ID = contentId[i]; 
String URL = SetConstant.URL_DOWNLOAD_CONTENT+contentId[i];

ここで、あなたは問題に直面しています。@Sofi Software LLCの回答として、メインスレッドによって値が変更されているグローバル変数を別のスレッドで使用しています。

二次発行:

  • プログレス バーを更新する場合は、その値を更新する必要があります。
    それ自体は更新されません。

AsyncTask (URL からのダウンロード) でイメージをダウンロードする必要があります。機能を効果的に実現するには、次のことを行う必要があります

  • 画像をダウンロードする AsyncTask を作成し (doInBackground() でダウンロードを実装)、postExecute() で画像が正常にダウンロードされたかどうかを追跡するブール値 (isImageDownloaded など) も用意します。
  • ダウンロードを開始する前に、進行状況バーも表示することを忘れないでください
  • AsyncTask を実行してダウンロードを開始します
  • android.os.CountDownTimer の拡張機能を作成して、最小時間をカウントダウンします
  • メソッド onFinish() で、追跡するブール値を確認します。false の場合は、AsyncTask をキャンセルして、意図したトースト/ダイアログをスローします
  • AsyncTask の複数のインスタンスを実行することはお勧めできません。executeOnExecutor() を使用して Executor で AsyncTask を実行できます。スレッドがシリアル方式で実行されていることを確認するには、SERIAL_EXECUTOR を使用してください。

以下のリソースが役立つかもしれません #

画像をダウンロードする必要がある場合は、進行状況バーを表示し、画像ビューに読み込みます

AsyncTask を使用して複数のファイル (ここでは画像用) をダウンロードする必要がある場合

編集:

http://developer.aiwgame.com/imageview-show-image-from-url-on-android-4-0.htmlから

new DownloadImageTask((ImageView) findViewById(R.id.imageView1))
            .execute("http://java.sogeti.nl/JavaBlog/wp-content/uploads/2009/04/android_icon_256.png"); }

public void onClick(View v) {
    startActivity(new Intent(this, IndexActivity.class));
    finish();

}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    ImageView bmImage;

    public DownloadImageTask(ImageView bmImage) {
        this.bmImage = bmImage;
    }

    protected Bitmap doInBackground(String... urls) {
        String urldisplay = urls[0];
        Bitmap mIcon11 = null;
        try {
            InputStream in = new java.net.URL(urldisplay).openStream();
            mIcon11 = BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return mIcon11;
    }

    protected void onPostExecute(Bitmap result) {
        bmImage.setImageBitmap(result);
    } }

Android ImageView および Progressbar 実装でのイメージ ダウンロードから

 // note that you could also use other timer related class in Android aside from this CountDownTimer, I prefer this class because I could do something on every interval basis
            // tick every 10 secs (or what you think is necessary)
            CountDownTimer timer = new CountDownTimer(30000, 10000) {

                @Override
                public void onFinish() {
                    // check the boolean, if it is false, throw toast/dialog
                }

                @Override
                public void onTick(long millisUntilFinished) {
                    // you could alternatively update anything you want every tick of the interval that you specified
                }

            };

            timer.start()
于 2012-12-21T05:43:31.460 に答える
2

次の行で:

SetConstant.CONTENT_ID = contentId[i];

グローバル変数を値に設定してから、同じ値に基づいて文字列 URL を作成し、それを AsyncTask に渡します。これが実行され、ダウンロードが完了すると、グローバル変数 SetConstant.CONTENT_ID に基づく名前のファイルが作成されます。

つまり、メインスレッドによって値が変更されているグローバル変数を別のスレッドで使用しています。異なるスレッドが異なる時間に更新されるため、あらゆる種類の奇妙な問題が発生するため、これを行わないでください。値または出力ファイルの名前を AsyncTask に渡します。DownloadFile のコンストラクターでそれを行い、値をフィールドに隠しておくことができます。

プログレス バーを更新する場合は、その値を更新する必要があります。それ自体は更新されません。タスク中に (doInBackground で) AsyncTask.publishProgress を呼び出し、onProgressUpdate を実装して進行状況ダイアログを更新します。

[編集: onProgressUpdate は実際に UI スレッドで呼び出されます。]

于 2012-12-21T02:48:09.103 に答える
0

最初に、画像アドレスに到達できるようにする別のクラスを作成します

次のように:

public class ImageDownloader extends AsyncTask {

    @Override
    protected Bitmap doInBackground(String... urls) {

        try {

            URL url = new URL(urls[0]);

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            connection.connect();

            InputStream inputStream = connection.getInputStream();

            Bitmap myBitmap = BitmapFactory.decodeStream(inputStream);

            return myBitmap;

        } catch (Exception e) {

            e.printStackTrace();

        }

        return null;
    }
}

次に、オブジェクトを作成して (ボタンによって呼び出されるメソッドを介して) そのクラスにアクセスし、次のように Bitmap タスクを実行します。

public class MainActivity extends Activity {

ImageView downloadedImg;

public void downloadImage(View view) {

    ImageDownloader task = new ImageDownloader();
    Bitmap myImage;

    try {
        myImage = task.execute("YOUR IMAGE ADDRESS ........").get();

        downloadedImg.setImageBitmap(myImage);

    } catch (Exception e) {

        e.printStackTrace();
    }

}  

忘れないでください: 1 - onCreat メソッドで imageView を定義します ==> DownloadImg = (ImageView) findViewById(R.id.imageView); 2 - ユーザー インターフェースのボタンで作成したメソッドをリンクする ==> (public void downloadImage(View view){}) 3 - マニフェスト ファイルで許可を求める

于 2018-05-21T17:32:57.077 に答える