2017-02-28 11 views
2

InfiniteScrollAdapterの画像にはURLImageURLImage.ImageAdapterの画像が含まれています。SimulatorのInfiniteScrollAdapterのURLImageにはNPE(コードネーム)が表示されます

シミュレータ(Iphone3GSまたはXoomまたはGoogleNexus7)で、InfiniteScrollAdapterが最初に表示されますが、ファイルはサーバー上に存在します。

注:このテストでは、データベースには1つのエントリしかありませんでした。したがって、下の画像には、同じ行(画像+テキスト)が3回重複して表示されます。ここで

Image tempPlaceholder = Image.createImage(
      ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, 
      ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, 
      ParametresGeneraux.accentColor); 
    Graphics gr = tempPlaceholder.getGraphics(); 
    gr.setAntiAliased(true); 
    gr.setColor(ParametresGeneraux.accentColor); 
    gr.fillArc(0, 0, ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, 0, 360); 

    EncodedImage roundPlaceholder = EncodedImage.createFromImage(tempPlaceholder, true); 

    final Image reportImage = URLImage.createToStorage(
          roundPlaceholder, 
          photoFilenameInStorage, 
          currentReport.getPhotoPath(), 
          ParametresGeneraux.RESIZE_SCALE_WITH_ROUND_MASK 
        ); 

そして:

NPE in InfiniteScrollAdapter

は、非表示のアイコンで順序は、私が画像をダウンロードするために使用されるコードがある

NPE with different order in the undisplayed icons

を異なる可能性がありますのでご注意くださいオーバーライドされたimageAdapterメソッド:

スタックトレース0
public final static URLImage.ImageAdapter RESIZE_SCALE_WITH_ROUND_MASK = new URLImage.ImageAdapter() { 
    @Override 
    public EncodedImage adaptImage(EncodedImage downloadedImage, EncodedImage placeholderImage) { 
     final Image[] tmp = new Image[1]; 

     if (!Display.getInstance().isEdt()) { 
      // The image scaling has to be called from EDT 
      Display.getInstance().callSeriallyAndWait(() -> { 

       tmp[0] = downloadedImage.scaledLargerRatio(placeholderImage.getWidth(), placeholderImage.getHeight()); 
       if (tmp[0].getWidth() > placeholderImage.getWidth()) { 
        int diff = tmp[0].getWidth() - placeholderImage.getWidth(); 
        int x = diff/2; 
        tmp[0] = tmp[0].subImage(x, 0, placeholderImage.getWidth(), placeholderImage.getHeight(), true); 
       } else if (tmp[0].getHeight() > placeholderImage.getHeight()) { 
        int diff = tmp[0].getHeight() - placeholderImage.getHeight(); 
        int y = diff/2; 
        tmp[0] = tmp[0].subImage(0, y, Math.min(placeholderImage.getWidth(), tmp[0].getWidth()), 
          Math.min(placeholderImage.getHeight(), tmp[0].getHeight()), true); 
       } 
      }); 
     } else { 
      tmp[0] = downloadedImage.scaledLargerRatio(placeholderImage.getWidth(), placeholderImage.getHeight()); 
      if (tmp[0].getWidth() > placeholderImage.getWidth()) { 
       int diff = tmp[0].getWidth() - placeholderImage.getWidth(); 
       int x = diff/2; 
       tmp[0] = tmp[0].subImage(x, 0, placeholderImage.getWidth(), placeholderImage.getHeight(), true); 
      } else if (tmp[0].getHeight() > placeholderImage.getHeight()) { 
       int diff = tmp[0].getHeight() - placeholderImage.getHeight(); 
       int y = diff/2; 
       tmp[0] = tmp[0].subImage(0, y, Math.min(placeholderImage.getWidth(), tmp[0].getWidth()), 
         Math.min(placeholderImage.getHeight(), tmp[0].getHeight()), true); 
      } 
     } 

     EncodedImage[] image2Return = new EncodedImage[1]; 
     if (!Display.getInstance().isEdt()) { 
      // The image scaling has to be called from EDT 
      Display.getInstance().callSeriallyAndWait(() -> { 
       Image roundMask = Image.createImage(tmp[0].getWidth(), tmp[0].getHeight(), 0xff000000); 
       Graphics gr = roundMask.getGraphics(); 
       gr.setColor(0xffffff); 

       gr.fillArc(0, 0, tmp[0].getWidth(), tmp[0].getHeight(), 0, 360); 
       Object mask = roundMask.createMask(); 
       tmp[0] = tmp[0].applyMask(mask); 
       image2Return[0] = EncodedImage.createFromImage(tmp[0], false); 
      }); 
     } else { 
      Image roundMask = Image.createImage(tmp[0].getWidth(), tmp[0].getHeight(), 0xff000000); 
      Graphics gr = roundMask.getGraphics(); 
      gr.setColor(0xffffff); 

      gr.fillArc(0, 0, tmp[0].getWidth(), tmp[0].getHeight(), 0, 360); 
      Object mask = roundMask.createMask(); 
      tmp[0] = tmp[0].applyMask(mask); 
      image2Return[0] = EncodedImage.createFromImage(tmp[0], false); 
     } 

     return image2Return[0]; 

    } 

、NPEがオーバーライドURLImage.ImageAdapterに由来すると思われる:

java.lang.IllegalArgumentExceptionが:0 でcom.codename1:作成した画像は、長さの所与 画像データに失敗しました.ui.Image.createImage(Image.java:654)at com.codename1.ui.EncodedImage.getInternal(EncodedImage.java:365)at com.codename1.ui.EncodedImage.getInternalImpl(EncodedImage.java:340) com.codename1.ui.EncodedImage.getHeight(EncodedImage.java:522)at com.codename1.ui.Image.scaledLa rgerRatio(Image.java:899)at com.my.application.ParametresGeneraux $ 1.lambda $ adaptImage $ 0(ParametresGeneraux.java:564) com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:95)at com.codename1.ui.Display.processSerialCalls(Display.java:1154)at com.codename1.ui.Display.edtLoopImpl(Display.java:1098)at com.codename1.ui.Display.invokeAndBlock(Display.java: 1207)at com.codename1.ui.Display.invokeAndBlock(Display.java:1244)at com.codename1.ui.URLImage $ DownloadCompleted.actionPerformed(URLImage.java:233) at com.codename1.ui.URLImage $ 4 .onSucess(URLImage.java:301)at com.codename1.ui.URLImage $ 4.onSucess(URLImage.java:297)at com.codename1.util.CallbackDispatcher.run(Cal lookDispatcher.java:53) com.codename1.ui.Display.processSerialCalls(Display.java:1154) com.codename1.ui.Display.edtLoopImpl(Display.java:1098) com.codename1.uiにあります。 Display.mainEDTLoop(Display.java:999)at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120)at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176) [EDT] 0:0:0.1 - コードネームつのリビジョン: e5c43877074c18b4b5c7748d000e5cfac75ab749 2318

[EDT] 0:0:0,1 - 例外:java.lang.NullPointerExceptionが - com.codename1でヌル java.lang.NullPointerExceptionが.impl.javase.JavaSEPort.scale(JavaSEPort.java: 3996)at com.codename1.ui.Image.scale(Image。java:1007) com.codename1.ui.Image.scaledImpl(Image.java:953) com.codename1.ui.Image.scaled(Image.java:918) com.codename1.impl.javaseにあります。 JavaSEPort $ 71.save(JavaSEPort.java:7659)at com.codename1.ui.EncodedImage.scaledEncoded(EncodedImage.java:626)at com.codename1.ui.EncodedImage.scaled(EncodedImage.java:653)at com .codename1.ui.Image.scaledLargerRatio(Image.java:904)at com.my.application.ParametresGeneraux $ 1.lambda $ adaptImage $ 0(ParametresGeneraux.java:564) at com.codename1.ui.RunnableWrapper.run(RunnableWrapper .java:95)at com.codename1.ui.Display.processSerialCalls(Display.java:1154)at com.codename1.ui.Display.edtLoopImpl(Display.java:1098)at com.codename1.ui.Display.invokeAndBlock(Display.java:1207)at com.codename1.ui.Display.invokeAndBlock(Display.java:1244)at com.codename1.ui.URLImage $ DownloadCompleted.actionPerformed(URLImage .java:233) com.codename1.ui.URLImage $ 4.onSucess(URLImage.java:301) com.codename1.ui.URLImage $ 4.onSucess(URLImage.java:297) com.codename1.util .CallbackDispatcher.run(CallbackDispatcher.java:53) com.codename1.ui.Display.processSerialCalls(Display.java:1154)at com.codename1.ui.Display.edtLoopImpl(Display.java:1098)at com .codename1.ui.Display.mainEDTLoop(Display.java:999)at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120) com.codename1.impl.Co denameOneThread.run(CodenameOneThread.java:176は)

また、.cn1ディレクトリ内一目ですべてがNPEなしで動作したときに表示されていないサフィックス「ImageURLTMP」とURLImageストレージファイル名を示しています。

最後に、このフォームに戻っても、すべて正常に動作します(画像はNPEなし)。私はimageAdapterにdownloadedImage nullnessをテストしようとしましたが、EncodedImageはnullではありません。

このNPEを回避するにはどうすればよいですか?

編集2017年3月1日

@Diamondと@Shaiからの回答の後、私はInfiniteScrollAdapter行で画面を埋めるために望んでいる、その結果、同時に同じ画像のダウンロードを起動するためにNPEが発生したと考えています(キャッシュにないため)。だから、解決策はInfiniteScrollAdapterがループするのを防ぐことです(有限になります)。どうやってやるの ?

また、404エラーがないことに注意してください。ネットワークモニタには、以下のように応答コード200が表示されます。しかし、イメージは3回ダウンロードするべきではありませんか?お使いのアダプタのチェックで

No 404

+0

ポストあなたのInfinteScrollerのために使用されるコードのスニペットをしてURLImage – Diamond

+0

私はそれを忘れてしまいました!私の編集@Diamondを見てください! – HelloWorld

答えて

1
以下にごImageAdapterを変更

public static final URLImage.ImageAdapter RESIZE_SCALE_WITH_ROUND_MASK = new URLImage.ImageAdapter() { 
    @Override 
    public EncodedImage adaptImage(EncodedImage downloadedImage, EncodedImage placeholderImage) { 
     Image tmp = downloadedImage.scaledLargerRatio(placeholderImage.getWidth(), placeholderImage.getHeight()); 
     if (tmp.getWidth() > placeholderImage.getWidth()) { 
      int diff = tmp.getWidth() - placeholderImage.getWidth(); 
      int x = diff/2; 
      tmp = tmp.subImage(x, 0, placeholderImage.getWidth(), placeholderImage.getHeight(), true); 
     } else if (tmp.getHeight() > placeholderImage.getHeight()) { 
      int diff = tmp.getHeight() - placeholderImage.getHeight(); 
      int y = diff/2; 
      tmp = tmp.subImage(0, y, Math.min(placeholderImage.getWidth(), tmp.getWidth()), 
        Math.min(placeholderImage.getHeight(), tmp.getHeight()), true); 
     } 
     Image roundMask = Image.createImage(tmp.getWidth(), tmp.getHeight(), 0xff000000); 
     Graphics gr = roundMask.getGraphics(); 
     gr.setColor(0xffffff); 
     gr.fillArc(0, 0, tmp.getWidth(), tmp.getHeight(), 0, 360); 
     Object mask = roundMask.createMask(); 
     tmp = tmp.applyMask(mask); 
     return EncodedImage.createFromImage(tmp, false); 
    } 

    @Override 
    public boolean isAsyncAdapter() { 
     return true; 
    } 
}; 

EDTをチェックする必要はありません。

あなたtempPlaceholder画像は、呼び出すコンポーネント最初に、あなたのロジックの最後に適用されていることを確認し、あなたのcallSerially()方法でURLImage

Image tempPlaceholder = Image.createImage(
     ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, 
     ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, 
     ParametresGeneraux.accentColor); 
Graphics gr = tempPlaceholder.getGraphics(); 
gr.setAntiAliased(true); 
gr.setColor(ParametresGeneraux.accentColor); 
gr.fillArc(0, 0, ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, 0, 360); 

myComponent.setIcon(tempPlaceholder); 


... 


//Then call this at the end of everything 
Display.getInstance().callSerially(() -> { 
    EncodedImage roundPlaceholder = EncodedImage.createFromImage(tempPlaceholder, true); 

    final Image reportImage = URLImage.createToStorage(
         roundPlaceholder, 
         photoFilenameInStorage, 
         currentReport.getPhotoPath(), 
         ParametresGeneraux.RESIZE_SCALE_WITH_ROUND_MASK 
       ); 
    myComponent.setIcon(reportImage); 
    myComponent.getComponentForm().repaint(); 
}); 

編集:

@シャイの答えに基づいて

、あなたは現在、同じ画像をダウンロードしているかどうかを確認して、別の画像が引っ張られるのを防ぐことができます。これは通常、競合が発生するので:

//Declare this at the top of your class 
final static private Map<String, Image> LOADED_URLS = new HashMap<>(); 

//Then change the URLImage image method to this 
Display.getInstance().callSerially(() -> { 
    EncodedImage roundPlaceholder = EncodedImage.createFromImage(tempPlaceholder, true); 

    final Image reportImage = LOADED_URLS.containsKey(photoFilenameInStorage) ? LOADED_URLS.get(photoFilenameInStorage) 
         : URLImage.createToStorage(
         roundPlaceholder, 
         photoFilenameInStorage, 
         currentReport.getPhotoPath(), 
         ParametresGeneraux.RESIZE_SCALE_WITH_ROUND_MASK 
       ); 
    LOADED_URLS.put(photoFilenameInStorage, reportImage); 
    myComponent.setIcon(reportImage); 
    myComponent.getComponentForm().repaint(); 
}); 
+0

ありがとう@Diamond、進行中のダウンロードのチェックが理にかなっています。私はそれを試してみましょう。 – HelloWorld

+0

'roundPlaceholder'ではなく 'tempPlaceholder'を最初に適用することがなぜ重要であるか説明できますか?既にダウンロードされているファイルをサーバーから取得すると、問題が発生します。実際に私が経験することは、データベースにエントリが不十分な場合(Nexus7のポートレートで3未満)、NPEが発生することだけです。しかし、あなたの提案された 'LOADED_URLS'でも、NPEはまだ起こります。 InfiniteScrollAdapterが同じ要素を複数回表示するのを防ぐのが最善の方法です。 – HelloWorld

+0

2つのうちのいずれかを使用できます。あなたは '404エラー'を返すキュー内のイメージがあるかどうかを確認するためにネットワークモニタを調べましたか? – Diamond

1

downloadedImage.getData()nullある場合。私はそれがないと仮定し、それは404エラーのページかそれに類似したものです。

この場合、アダプタは例外をキャッチして、イメージが存在しないときに見えるものと一致するフォールバックを返します。

これは、システムがtmpファイルを見て、ダウンロードが進行中であるとみなしてからダウンロードコードを再度呼び出さないので、もう一度動作します。 tmpファイルは、最終的にダウンロード可能なファイルに名前が変更されます。

+0

ありがとう@Shai。私の質問に記載されているように、ファイルはサーバー上に存在しません(404はありません)!しかし、私はあなたが "それは404ではない"という意味だと思います。どこでNPEを捕まえることができるのですか? 'URLImage'クラスでオーバーライドするエラーメソッドが見つかりません? – HelloWorld

+0

'tmp [0] = downloadedImage.scaledLargerRatio(placeholderImage.getWidth()、placeholderImage.getHeight());を囲みます。 'try-catchブロックではNPEをキャッチしません。しかし、サーバー上の元のイメージは、(少なくともキャッシュがクリアされるまでは)「決して」表示されません。 'InfiniteScrollAdapter'が2回以上行を表示しないようにする方法はありますか? 'FiniteScrollAdapter'クラスが見つかりませんでした。 – HelloWorld

+0

画像の命名規則が厳格な場合(たとえば共通の接頭辞を使用して)、保存された要素を繰り返し処理し、削除できるTMPファイルを確認できます。また、古いイメージを削除して強制的にリフレッシュすることもできます。私たちの顧客の1人は、すべてのアプリの起動時に自動的にそのことを行いました。 –

関連する問題