问题
I've gone through stackoverflow and all the similar answers - but have found them not of use.
Can anyone please point out why this is not working? It should be simple: update the image every 6 seconds (will be every 3 mins but for testing I've put it as 6 seconds).
What the code does is - goes through each of the 4 images step by step but does not change the image. HOWEVER when it gets to the last image - it does change it(??).
Questions:
- What's wrong with this?
- Why would it only update the last image?
- If I start the code with just a "post" to the handler instead of a "postDelayed" - the tablet just stays with a black screen. Why do I have to start the code with a delay to make it work?
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
}
}
});
}
Thanks!
EDIT: Doesn't work if I post it to the imageview thread either, instead of the handler.
descriptionImage.postDelayed(timerRunnable, 1000);
回答1:
What's wrong with this?
while the UI Thread is busy ( while (start)
) , waiting to your condition to became true ( if (mins >= 0.1f) {
), it can't take care of the rest (like drawing).
Why would it only update the last image?
because it can draw only when if (currentIndex < pictureIds.length) {
is not true, start
becomes false, and the UI thread can finally draw
If I start the code with just a "post" to the handler instead of a "postDelayed" - the tablet just stays with a black screen. Why do I have to start the code with a delay to make it work?
see point 1.
if you want to change your image every 3 seconds, you could keep using 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);
回答2:
The problem you're facing is that your while loop is running on the main thread. This means the UI never has a chance to update until after the while loop ends (thus why you're only seeing the final image). Try this as your start
function:
private void start() {
timerRunnable = new Runnable() {
@Override
public void run() {
if (currentIndex < pictureIds.length) {
loadImage();
currentIndex++;
handler.postDelayed(timerRunnable, 6 * 1000);
}
}
};
handler.post(timerRunnable);
}
来源:https://stackoverflow.com/questions/44506961/changing-image-on-android-thread