简体   繁体   中英

Animated GIF Freezes in WebView while timer is running

I have a WebView with an animated gif loaded in it. I also have a countdown timer and when it's up it loads a different animated gif.

When the timer is running the gif doesn't animated. What is the best way to fix this?

public class Practice extends SherlockActivity implements
    AnimationLayout.Listener {
public final static String TAG = "Practice";

protected ListView mList;
protected AnimationLayout mLayout;
protected String[] mStrings = { "Lesson 1", "Lesson 2", "Lesson 3",
        "Lesson 4", "Lesson 5", "Lesson 6", "Lesson 7", "Lesson 8",
        "Lesson 9", "Lesson 10" };
String[] lesson1;
String[] lesson2;
String[] lesson3;
String[] lesson4;
String[] lesson5;
String[] lesson6;
String[] lesson7;
String[] lesson8;
String[] lesson9;
String[] lesson10;
Button buttonA;
Button buttonB;
Button buttonC;
Button buttonD;
String[] prev;
int numCorrect;
int numWrong;
int i;
String answer;
static Random rnd;
Random r;
final String alphabet = "ABCD";
final int N = 4;
char letter = 'A';
String rand = " ";
int index;
WebView sign;
long mMilliseconds = 10000;
TextView score;

CountDownTimer mCountDownTimer = new CountDownTimer(mMilliseconds, 10){
    @Override
    public void onFinish() {
        score.setText("0");
    }

    public void onTick(long millisUntilFinished){
        score.setText(String.valueOf(millisUntilFinished/100));
    }
};
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_practice);

    prev = new String[100];
    rnd = new Random();
    r = new Random();
    score = (TextView) findViewById(R.id.textView1);

    lesson1 = getResources().getStringArray(R.array.lesson_1);
    lesson2 = getResources().getStringArray(R.array.lesson_2);
    lesson3 = getResources().getStringArray(R.array.lesson_3);
    lesson4 = getResources().getStringArray(R.array.lesson_4);
    lesson5 = getResources().getStringArray(R.array.lesson_5);
    lesson6 = getResources().getStringArray(R.array.lesson_6);
    lesson7 = getResources().getStringArray(R.array.lesson_7);
    lesson8 = getResources().getStringArray(R.array.lesson_8);
    lesson9 = getResources().getStringArray(R.array.lesson_9);
    lesson10 = getResources().getStringArray(R.array.lesson_10);

    rand = lesson1[rnd.nextInt(lesson1.length)];

    mLayout = (AnimationLayout) findViewById(R.id.animation_layout);
    mLayout.setListener(this);

    mList = (ListView) findViewById(R.id.sidebar_list);
    mList.setAdapter(new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_multiple_choice, mStrings));
    mList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    mList.setItemChecked(0, true);

    sign = new WebView(getApplicationContext());
    sign = (WebView) findViewById(R.id.webView1);

    buttonA = (Button) findViewById(R.id.option1_button);
    buttonB = (Button) findViewById(R.id.option2_button);
    buttonC = (Button) findViewById(R.id.option3_button);
    buttonD = (Button) findViewById(R.id.option4_button);

    setSign();
}

public void onClickContentButton(View v) {
    mLayout.toggleSidebar();
}

public void onClickA(View v) {
    if (answer == buttonA.getText().toString()) {
        numCorrect += 1;
    } else {
        numWrong += 1;
    }

    setSign();
}

public void onClickB(View v) {
    if (answer == buttonB.getText().toString()) {
        numCorrect += 1;
    } else {
        numWrong += 1;
    }

    setSign();
}

public void onClickC(View v) {
    if (answer == buttonC.getText().toString()) {
        numCorrect += 1;
    } else {
        numWrong += 1;
    }

    setSign();
}

public void onClickD(View v) {
    if (answer == buttonD.getText().toString()) {
        numCorrect += 1;
    } else {
        numWrong += 1;
    }

    setSign();
}

public void onClick(View view) {

}

@Override
public void onBackPressed() {
    if (mLayout.isOpening()) {
        mLayout.closeSidebar();
    } else {
        finish();
    }
}

@Override
public void onSidebarOpened() {
    Log.d(TAG, "opened");
}

@Override
public void onSidebarClosed() {
    Log.d(TAG, "opened");
}

@Override
public boolean onContentTouchedWhenOpening() {
    Log.d(TAG, "going to close sidebar");
    mLayout.closeSidebar();
    return true;
}

public void setSign() {

    answer = pickRandomAnswer(prev[i]);

    letter = alphabet.charAt(r.nextInt(N));

    sign.loadUrl("file:///android_asset/" + answer.toLowerCase() + ".html");

    prev[i] = answer;

    buttonA.setText(pickRandomAnswer(answer));
    buttonB.setText(pickRandomAnswer(buttonA.getText().toString()));
    buttonC.setText(pickRandomAnswer(buttonB.getText().toString()));
    buttonD.setText(pickRandomAnswer(buttonC.getText().toString()));

    if (letter == 'A')
        buttonA.setText(answer);
    if (letter == 'B')
        buttonB.setText(answer);
    if (letter == 'C')
        buttonC.setText(answer);
    if (letter == 'D')
        buttonD.setText(answer);

    if(i>= 95){
        i = 0;
    } else {
        i += 1;
    }
    mCountDownTimer.start();
}


public String pickRandomAnswer(String str) {

    do{
        index = rnd.nextInt(10+1);

        if(index == 1){
            if(mList.isItemChecked(0)){
                rand = lesson1[rnd.nextInt(lesson1.length)];
            }
        }

        if(index == 2){
            if(mList.isItemChecked(1)){
                rand = lesson2[rnd.nextInt(lesson2.length)];
            }
        }

        if(index == 3){
            if(mList.isItemChecked(2)){
                rand = lesson3[rnd.nextInt(lesson3.length)];
            }
        }

        if(index == 4){
            if(mList.isItemChecked(3)){
                rand = lesson4[rnd.nextInt(lesson4.length)];
            }
        }

        if(index == 5){
            if(mList.isItemChecked(4)){
                rand = lesson5[rnd.nextInt(lesson5.length)];
            }
        }

        if(index == 6){
            if(mList.isItemChecked(5)){
                rand = lesson6[rnd.nextInt(lesson6.length)];
            }
        }

        if(index == 7){
            if(mList.isItemChecked(6)){
                rand = lesson7[rnd.nextInt(lesson7.length)];
            }
        }

        if(index == 8){
            if(mList.isItemChecked(7)){
                rand = lesson8[rnd.nextInt(lesson8.length)];
            }
        }

        if(index == 9){
            if(mList.isItemChecked(8)){
                rand = lesson9[rnd.nextInt(lesson9.length)];
            }
        }

        if(index == 10){
            if(mList.isItemChecked(9)){
                rand = lesson10[rnd.nextInt(lesson10.length)];
            }
        }

    } while ( rand.contains("Grammar")| rand == str);
    return rand;
}

static void shuffleArray(String[] words) {
    for (int i = words.length - 1; i >= 0; i--) {
        int index = rnd.nextInt(i + 1);
        String a = words[index];
        words[index] = words[i];
        words[i] = a;
    }
}
}

After looking at your code one possible reason for your issue is that you are updating a TextView in the UI on every call of the onTick() method of the CountDownTimer . The documentation for CountDownTimer only mentions that it is called "at a regular interval" so I'm not sure how often it is called, but it seems to me that you shouldn't do something that updates the UI on every onTick() call, especially when you have a WebView animating a gif (a rather resource intensive task). I suggest doing this in your onTick() method:

public void onTick(long millisUntilFinished){
   if (mLastMillisUntilFinished == 0 ||
       mLastMillisUntilFinished - millisUntilFinished > UI_UPDATE_INTERVAL) {
       score.setText(String.valueOf(millisUntilFinished/UI_UPDATE_INTERVAL));
       mLastMillisUntilFinished = millisUntilFinished;
   }
}

This way you are only updating the UI every UI_UPDATE_INTERVAL milliseconds (just define that to your desired interval, like 100 in your case to update every 10th of a second). This protects you from unnecessarily updating the UI too often and will allow the WebView to do it's job.

As a last resort, there is a more complicated (no too complicated) solution that should get you the performance you want. See this GifView class in one of my github repos:

https://github.com/bduncavage/catoverflow/blob/master/src/jp/tomorrowkey/android/gifplayer/GifView.java

I found that class in an abandoned project on google code and used it in a project that required I draw animated gifs to a Canvas. It needed serious work as it was not threadsafe at all, and it hogs memory, BUT, it does work.

You can use GifView pretty easily and it should be much faster than using a WebView just to animate a gif. You will need the GifDecoder class as well.

Cheers.

As a last resort I would say you can also split your GIFs into frames then render them in android using drawables. Drawables reference

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM