2013-07-27 57 views
1

我在做什麼: 我有幾個JPG文件保存在「資產」文件夾下的子文件夾。我的應用程序應該進入這個子文件夾,加載第一個文件,顯示它30秒,然後加載第二個文件,顯示它30秒,等等,直到最後一個文件。這是在一個循環中完成的。ImageView無法一一顯示圖像

我有什麼問題: 該應用程序經歷了循環的所有迭代。它正確加載每個文件,正確報告每個圖像的寬度和高度。但是,屏幕是黑色的,沒有顯示圖像,直到整個循環結束。然後顯示最後的圖像。

這裏是我的layout.xml文件(我想處理不同尺寸的圖像,但以後會擔心吧):

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/mylayout_id" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" > 

    <ImageView 
     android:id="@+id/image_display" 
     android:layout_width="400dp" 
     android:layout_height="400dp" > 
    </ImageView> 

    <Button 
     android:id="@+id/button_start" 
     style="?android:attr/buttonStyleSmall" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:onClick="pressedStart" 
     android:text="@string/btn_start" /> 
</LinearLayout> 

這裏是我的代碼

public class MyImageActivity extends Activity { 
    private final String TAG = "MyImageActivity"; 

    private ImageView mIV; 
    private Bitmap mFaceBitmap; 
    private AssetManager mAssetMan = null; 
    private String[] mImgFileNames = null; 
    private int mBitmapWidth; 
    private int mBitmapHeight; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     Log.e(TAG, "onCreate"); 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.mylayout); 
     mIV = (ImageView) findViewById(R.id.image_display); 
    } 

    @Override 
    protected void onResume() { 
     Log.e(TAG, "onResume"); 
     super.onResume(); 
     mAssetMan = getAssets(); 
    } 

    public void pressedStart(View view) { 
     Log.e(TAG, "pressedStart"); 
     try { 
      mImgFileNames = mAssetMan.list("my_subfolder"); 
     } catch (IOException e1) { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 
     Log.d(TAG, "mImgFileNames = " + mImgFileNames); 
     Log.d(TAG, "number of image files = " + mImgFileNames.length); 

     for (int i = 0; i < mImgFileNames.length; i++) { 
      Log.d(TAG, "image file name = " + mImgFileNames[i]); 

      mIV.setImageDrawable(null); 
      mIV.invalidate(); 
      InputStream istr = null; 
      try { 
       istr = mAssetMan.open("my_subfolder" + mImgFileNames[i]); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

      // load the photo 
      Bitmap b = BitmapFactory.decodeStream(istr); 
      mFaceBitmap = b.copy(Bitmap.Config.RGB_565, true); 
      b.recycle(); 

      mBitmapWidth = mFaceBitmap.getWidth(); 
      mBitmapHeight = mFaceBitmap.getHeight(); 
      Log.d(TAG, "mBitmapWidth = " + mBitmapWidth); 
      Log.d(TAG, "mBitmapHeight = " + mBitmapHeight); 

      Drawable drawable = new BitmapDrawable(getResources(), mFaceBitmap); 
      mIV.setImageDrawable(drawable); 
      mIV.invalidate(); 
      SystemClock.sleep(5000); 
     } 
    } 
} 

我發現了一些關於類似問題的其他討論herehere。我嘗試了一些建議的解決方案,例如添加setImageDrawable(null)以強制ImageView更新;那對我不起作用。

我的方法有什麼問題嗎?我非常感謝你的幫助和建議。

在此先感謝&有一個愉快的週末。

回答

1

發生這種情況的原因是您將新圖像置於持有者內部,並調用invalidate使其顯示,但您轉過身並將UI線程休眠5秒鐘,因此無法更新它。當系統更新它時,它已經移動到下一個圖像。我會使用AsyncTask在後臺加載下一個Image,然後在後臺線程中放置一個5秒的定時器,然後用新數據更新UI。

編輯
這裏是你的代碼的重新設計版本,可以運行,如果這是你確切的代碼。如果不是,你應該沒問題。 (如果格式不好,那是因爲我的工作使用IE8仍然和它不會讓我看到了格式化。當我回家我會改正。)

public class MyImageActivity extends Activity { 
     private final String TAG = "MyImageActivity"; 
     private ImageView mIV; 

     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      Log.e(TAG, "onCreate"); 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.mylayout); 
      mIV = (ImageView) findViewById(R.id.image_display); 
     } 

     @Override 
     protected void onResume() { 
      Log.e(TAG, "onResume"); 
      super.onResume(); 
     } 

     public void pressedStart(View view) { 
     new SlideShowTask().execute(); 
     } 

    private class SlideShowTask extends AsyncTask<Void, Drawable, Void>{ 

     private Bitmap mFaceBitmap; 
      private AssetManager mAssetMan = null; 
      private String[] mImgFileNames = null; 
      private int mBitmapWidth; 
      private int mBitmapHeight; 

     @Override 
     Protected Void doInBackground(Void... params){ 
     mAssetMan = getAssets(); 
     Log.e(TAG, "pressedStart"); 
       try { 
        mImgFileNames = mAssetMan.list("my_subfolder"); 
       } catch (IOException e1) { 
        // TODO Auto-generated catch block 
        e1.printStackTrace(); 
       } 
       Log.d(TAG, "mImgFileNames = " + mImgFileNames); 
       Log.d(TAG, "number of image files = " + mImgFileNames.length); 

      for (int i = 0; i < mImgFileNames.length; i++) { 
       Log.d(TAG, "image file name = " + mImgFileNames[i]); 

       InputStream istr = null; 
       try { 
        istr = mAssetMan.open("my_subfolder/" + mImgFileNames[i]); 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 

       // load the photo 
       Bitmap b = BitmapFactory.decodeStream(istr); 
       mFaceBitmap = b.copy(Bitmap.Config.RGB_565, true); 
       b.recycle(); 

       mBitmapWidth = mFaceBitmap.getWidth(); 
       mBitmapHeight = mFaceBitmap.getHeight(); 
       Log.d(TAG, "mBitmapWidth = " + mBitmapWidth); 
       Log.d(TAG, "mBitmapHeight = " + mBitmapHeight); 

       Drawable drawable = new BitmapDrawable(getResources(), mFaceBitmap); 
     publishProgress(drawable); 
       SystemClock.sleep(5000); 
      } 
     } 

     @Override 
     Protected Void onProgressUpdate(Drawable... values){ 
     super.onProgressUpdate(values); 
     mIV.setImageDrawable(values[0]); 
     mIV.invalidate(); 
     } 
    } 
} 
+0

一個的AsyncTask不能在循環中使用的鏈接。這是否意味着我必須將循環放入AsyncTask? – hubeir

+0

@hubeir沒有你做的是傳遞你想要在你的應用程序中加載的圖像在後臺執行。獲取圖像,然後使用發佈進度更新背景上的圖像。然後再睡5秒鐘。它會看起來像psudocode:'doInBackgroupd(String params ....){for(int i = 0; i <= 5; i ++){bitmap b = getimage(imagename); publishprogress(b)中; sleep(5000);}}'這樣循環會在AsyncTask中發生,直到它顯示5張圖片,每張圖片之間有5秒。我會在一秒鐘之內用例子更新我的答案。 – ObieMD5

+0

@hubeir我剛剛完成在我的筆記本電腦上重寫您的代碼。我將在大約一個小時後到家,所以我會在一個編輯中發佈它。我測試了它,它工作正常,所有圖片顯示5秒鐘。 – ObieMD5

1

這是因爲你把主UI穿線睡覺。 而你永遠不應該那樣做。因爲這意味着整個應用程序將掛起5秒鐘,這是錯誤的。

您應該創建一個新線程並從那裏更新UI,如代碼 這是最簡單的。

runOnUiThread(new Runnable(){ 

    @Override 
    public void run(){ 
     <--Your Code Here --> 
     <--sleep for 5000ms--> 
    } 
}); 

或使用Handler或ASynkTask。 這裏有很多很好的教程。

+0

我試過runOnUiThread(),但代碼沒有改變它的行爲。我可能會做對了。在Handler和AsyncTask之間,這是首選的方式? – hubeir

1

嘗試使用新線程或Runnable,並將您的代碼添加到運行函數並使該線程進入睡眠狀態。 由於您正在更新您的用戶界面,您還需要一個處理程序。檢查以下

www.vogella.com/articles/AndroidBackgroundProcessing/article.html