Я работаю с Android 2.3.3. У меня возникла проблема, чтобы обновить представление активности после поворота экрана.
Моя активность имеет переменную (счетчик), TextView (отображает значение счетчика), кнопку (увеличивать счетчик и показывать ее) и TimerTask (увеличивать счетчик и показывать его тоже). Он работает правильно. Мой TextView показывает новое значение после каждого события из Button или TimerTask.
Он работает, пока я не поворачиваю свой телефон. Событие TimerTask больше не обновляет мой TextView. Кнопка и экран поворота могут изменить мой вид. Мой TimerTask по-прежнему увеличивает мою переменную, но на экране нет изменений. Я проверил, TimerTask все еще выполняется и выполняется.
Это не мой настоящий проект, это просто та часть, где есть моя ошибка.
Моя единственная деятельность:
package com.test;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class TestRefreshActivity extends Activity {
static TimerTask mTimerTask=null;
static Timer t=new Timer();
final Handler handler = new Handler();
static int counter=0;
//-------------------------------------------------
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//create and run the timer
if(mTimerTask==null){
Log.d("Test","new TimerTask");
mTimerTask = new TimerTask() {
public void run() {
handler.post(new Runnable(){
public void run(){
counter++;
refreshCounter();
Log.d("TIMER", "TimerTask run");
}
});
}
};
t.schedule(mTimerTask, 500, 3000);
}
Log.d("Test","--onCreate--");
refreshCounter();
}
//-------------------------------------------------
@Override
public void onBackPressed() {
super.onBackPressed();
mTimerTask.cancel();
TestRefreshActivity.this.finish();
}
//-------------------------------------------------
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("Test","--onDestroy--");
}
//-------------------------------------------------
public void onBtnClick(View view){
counter++;
refreshCounter();
}
//-------------------------------------------------
//the only function which refreshes the TextView
private void refreshCounter(){
Runnable run = new Runnable(){
public void run(){
TextView textView = (TextView)findViewById(R.id.textView1);
textView.setText("counter="+counter);
textView.invalidate();
}
};
synchronized(run){
TestRefreshActivity.this.runOnUiThread(run);
}
}
}
И мое единственное мнение:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onBtnClick"
android:text="Button" />
</LinearLayout>
Я не понимаю, почему мой TimerTask не может изменить представление после вращения. То, что я знаю, вращение разрушает мою деятельность для его воссоздания, но выживают только статические переменные.
Спасибо за вашу помощь.
С Уважением,
android:configChanges="keyboardHidden|orientation"
- это плохое решение, которое не поощряется рекомендациями. Это спасет вас только от поворота экрана, но ваше приложение будет по-прежнему непригодным для использования после того, как ваша активность будет убита андроидом, когда он будет на заднем плане.
Посмотрите, что вы делаете. Вы предоставляете ссылку на обработчик статического таймера. Когда вы поворачиваете свой телефон, активность воссоздается (значит, один из них уничтожен, а другой создан). Ваша активность уничтожается, но статические члены все еще живут, и они все еще содержат ссылку на обработчик для активности, которая мертва.
Затем создается новый вид с новым обработчиком, но ваш timertask ничего не знает об этом.
Таким образом, у вас есть статический таймер, который обновляет недействительный обработчик и активность, которая ничего не делает.
Я бы сбросил статику и сохранил текущее значение таймера в пакете onSaveInstanceState.
Или (даже проще для вас) создать сеттер для обработчика в вашем TimerTask, и когда вы это сделаете, проверьте if(mTimerTask==null){
и посмотрите, что этот таймер уже создан, установите в нем новый обработчик (mTimerTask.setHandler(yourActivityHandler)
), поэтому при создании новой активности ваш timertask будет публиковать в новом обработчике.
откройте файл манифеста Android и измените значение в теге Activity следующим образом:
<activity android:name=".aaa"
android:configChanges="keyboardHidden|orientation"
android:label="@string/app_name"></activity>