2017-06-12 48 views
1

我已經通過了stackoverflow和所有類似的答案 - 但發現它們沒有用。更改Android線程上的圖像

任何人都可以請指出爲什麼這不工作?應該很簡單:每6秒更新一次圖像(每隔3分鐘更新一次,但測試時間爲6秒)。

代碼的作用是 - 逐步瀏覽4個圖像中的每一個,但不會更改圖像。但是當它到達最後的圖像時 - 它確實會改變它(??)。

問題:

  1. 這有什麼錯呢?
  2. 它爲什麼只更新最後一張圖片?
  3. 如果我只是通過一個「帖子」來處理程序而不是「postDelayed」來開始代碼 - 平板電腦只是停留在黑屏。爲什麼我必須延遲啓動代碼才能使其工作?

int currentIndex = 0; 
boolean start = false; 
ImageView descriptionImage; 
private Runnable timerRunnable; 
long startTime = 0; 
private Handler handler; 

int[] pictureIds = new int[]{R.drawable.hang, R.drawable.dog, R.drawable.coffee, R.drawable.about}; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    pictureDescription = new ArrayList<String>(); 
    handler = new Handler(Looper.getMainLooper()); 
} 

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View v = inflater.inflate(R.layout.fragment_picture_test, container, false); 
    descriptionImage = (ImageView) v.findViewById(R.id.iv_picture); 

    return v; 
} 

@Override 
public void onViewCreated(View view, Bundle savedInstanceState) { 
    super.onViewCreated(view, savedInstanceState); 
    start(); 
} 

private void start() { 

    start = true; 
    startTime = System.currentTimeMillis(); 
    loadImage(); 
    timerRunnable = new Runnable() { 

     @Override 
     public void run() { 
      while (start) { 
       long time = System.currentTimeMillis() - startTime; 
       float mins = (float) time/(60 * 1000); 
       if (mins >= 0.1f) { 
        startTime = System.currentTimeMillis(); 
        if (currentIndex < pictureIds.length) { 
         currentIndex++; 
         loadImage(); 
        } 
       } 
      } 
     } 
    }; 
    handler.postDelayed(timerRunnable, 1000); 
} 

private void loadImage() { 
    getActivity().runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      if (currentIndex < pictureIds.length) { 
       descriptionImage.setImageResource(pictureIds[currentIndex]); 
      } else { 
       start = false; // finish 
      } 

     } 
    }); 
} 

謝謝!

編輯:如果我將它發佈到imageview線程,而不是處理程序,則不起作用。

descriptionImage.postDelayed(timerRunnable,1000);

+0

你的代碼不是用這個'while(start)'循環掛起UI線程嗎? –

+0

除了你得到的這兩個答案之外,別忘了在你的片段的onPause中調用Handler#removeCallback。 –

+0

順便說一下,'runOnUiThread(action)'相當於'uiHandler。交的(動作);'。既然你已經有UI處理器,爲什麼'getActivity()。runOnUiThread()'? –

回答

2

這是怎麼回事?

而UI線程繁忙(while (start)),等待你的條件成真(if (mins >= 0.1f) {),它不能照顧剩下的(像圖)的。

Why would it only update the last image? 

,因爲它可以借鑑,只有當if (currentIndex < pictureIds.length) {是不正確的,start變成假的,UI線程終於可以畫

如果我開始只是一個「後」的代碼,該處理程序,而不是 「postDelayed」 - 平板電腦只是停留在黑屏。爲什麼我 必須延遲啓動代碼才能使其工作?

看點1.

如果你想改變你的形象每隔3秒

,你可以繼續使用處理器#postDelayed。例如。

start = true; 
startTime = System.currentTimeMillis(); 
loadImage(); 
timerRunnable = new Runnable() { 

    @Override 
    public void run() { 
     currentIndex = currentIndex++ % pictureIds.length; 
     loadImage(); 
     handler.postDelayed(this, 3000); 
    } 
}; 
handler.postDelayed(timerRunnable, 3000); 
+0

這使得總體感覺!我是一個數字。所以如果我想要這個工作在一個新的線程上 - 我會創建一個HandlerThread來運行它?並將UI更改發佈到getActivity.runOnUIThread? – LifeQuestioner

+1

正常的'線程'就足夠了。順便說一句,我會避免任何[忙等待](https://en.wikipedia.org/wiki/Busy_waiting)機制 – Blackbelt

2

您面臨的問題是您的while循環在主線程上運行。這意味着UI永遠不會有機會更新,直到while循環結束(因此爲什麼只看到最終圖像)。試試這個作爲你的start函數:

private void start() { 

    timerRunnable = new Runnable() { 

     @Override 
     public void run() { 
      if (currentIndex < pictureIds.length) { 
       loadImage(); 
       currentIndex++; 
       handler.postDelayed(timerRunnable, 6 * 1000); 
      } 
     } 
    }; 
    handler.post(timerRunnable); 
} 
+0

這使得總體感!我是一個數字。所以如果我想要這個工作在一個新的線程上 - 我會創建一個HandlerThread來運行它?並將UI更改發佈到getActivity.runOnUIThread? – LifeQuestioner

+0

從功能上來說,是的,你可以使用一個新的'Thread'並且UI不會被阻塞。但是,在你的情況下,你所做的一切都在UI上,所以在線程之間切換將是不必要的。使用'handler.postDelayed'函數比在後臺線程中持續運行while循環要好得多(在另一個答案中提到的「忙等待」機制)。 – Adam