更改Android线程上的图像

时间:2017-06-12 19:05:48

标签: android multithreading user-interface handler runnable

我已经完成了stackoverflow和所有类似的答案 - 但发现它们没有用。

任何人都可以指出为什么这不起作用?它应该很简单:每6秒钟更新一次图像(每隔3分钟更新一次,但测试时我会将其设为6秒)。

代码的作用是 - 逐步浏览4个图像中的每个图像,但不会更改图像。然而,当它到达最后一个图像时 - 它确实改变了它(??)。

问题:

  1. 这有什么问题?
  2. 为什么只更新最后一张图片?
  3. 如果我只使用" post"来启动代码到处理程序而不是" postDelayed" - 平板电脑只是黑屏。为什么我必须延迟启动代码才能使其正常工作?
  4. 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
                }
    
            }
        });
    }
    

    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);

2 个答案:

答案 0 :(得分:2)

  

这有什么问题?

当UI线程忙(while (start)),等待你的条件变为真(if (mins >= 0.1f) {)时,它无法处理其余部分(如绘图)。

Why would it only update the last image?

因为它只能在if (currentIndex < pictureIds.length) {不为真时绘制,start变为false,UI线程最终可以绘制

  

如果我只使用“post”启动代码而不是a   “postDelayed” - 平板电脑只是黑屏。我为什么会   必须延迟启动代码才能使其正常工作?

见第1点。

如果你想每隔3秒更改一次图像,你可以继续使用Handler#postDelayed。 E.g。

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);

答案 1 :(得分: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);
}