Android - не удается получить доступ к TextView внутри таймера в службе - PullRequest
0 голосов
/ 30 сентября 2011

Я столкнулся со следующей проблемой:

public class StatCounterService extends Service {


  private TimerTask updateTask_ref = new TimerTask() {

            //Get the element by Id as common practice in Android
        TextView hungerValue_ref = (TextView)layout.findViewById(R.id.hungerValue);
        @Override
        public void run() {

          //Every X Seconds, the Tamagotchi loses Hunger Points
          int hunger = (int) (getHunger()-1);
                  //Updating Model (DataBase)
          updateHunger(hunger);

                  //Now I want to update the TextView, but this hungerValue is Null 
          hungerValue_ref.setText(new Long(getHunger()).toString());
        }
      };
}

Я думаю, что проблема в том, что я ищу идентификатор Представления внутри Службы, также внутри вложенного Класса (таймерная задача). Служба работает, я просто получаю нулевой указатель на "hungerValue". Любые идеи, как я мог решить это? большое спасибо! Daniel

РЕДАКТИРОВАТЬ: я сейчас пытаюсь обновить представление в таймер из деятельности, вот идея:

public class MainWindowActivity extends Activity {


Timer timer_ref;
TextView hungerValue_ref;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

            //Change the View I want to change initally (getting Value from Database)
    updateHungerView();
            //Start Timer
    timer_ref = new Timer("StatCounterTimer");
    timer_ref.schedule(updateTask_ref, 1000L, 10000L);

}
    //The Timer from within I want to change the View every X seconds
private TimerTask updateTask_ref = new TimerTask() {
    @Override
    public void run() {
                    //Line Throws Exception, see Method below
        updateHungerView();
    }
};
    /**
     * Important Part
     */

    public void updateHungerView() {
    hungerValue_ref = (TextView) findViewById(R.id.hungerValue);
    hungerValue_ref.setText(new Long(getHunger()).toString());

}

когда я пытаюсь изменить вид из своей деятельности, я получаю это:

09-30 11:54:48.967: ERROR/AndroidRuntime(30476): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Ответы [ 4 ]

2 голосов
/ 30 сентября 2011

Вы пытаетесь работать с составной частью макета изнутри службы, но вы можете работать только с макетом из связанной деятельности. Служба не знает, находится ли активность на вершине, когда она выполняет свой код - экземпляр Activity может еще даже не существовать.

Наилучшим подходом к разрешению службы на обновление дисплея является передача намерения от службы:

Intent intent = new Intent();
intent.setAction("my.intent.action.name");
sendBroadcast(intent);

Затем в своей деятельности вы создаете экземпляр BroadcastReceiver для обработки намерения.

private BroadcastReceiver receiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("my.intent.action.name")) {
            // do something with the UI here
        }
    }
};

Вам также необходимо зарегистрировать приемник вещания в методе onResume ():

IntentFilter filter = new IntentFilter("my.intent.action.name");  
registerReceiver(receiver, filter);

И отмените регистрацию в вашем методе onPause ():

unregisterReceiver(receiver);

Вы не можете использовать статический внутренний класс для своего экземпляра BroadcastReceiver, потому что он не сможет делать такие вещи, как:

MyActivity.this.getContext()

или

MyActivity.this.findViewById(R.id.my_ui_component)

Надеюсь, это поможет!

1 голос
/ 30 сентября 2011

Я думаю, что это общая проблема с Android.FindViewById относится к макету и должен вызываться после setContentView, если я хорошо помню.Это может помочь вам:

http://www.anddev.org/solved_why_does_findviewbyid_return_null-t557.html

1 голос
/ 30 сентября 2011

Мне кажется, что вы пытаетесь найти и обновить TextView, который может быть невидимым / раздутым (например, он содержит действие, которое было уничтожено / остановлено / приостановлено).

Я предполагаю, что вы хотите использовать сервис, потому что он может продолжать работать, даже если ваше приложение отодвинется на задний план или будет убито. Тем не менее, я думаю, что в вашей ситуации изменение вашего дизайна может быть предпочтительным.

Вместо запуска службы - сохраняйте метку времени, как только ваше приложение будет приостановлено (в методе onPause() видимой активности). Затем, когда пользователь возобновляет работу приложения (будет вызываться метод onResume), вы вычисляете время между ранее сохраненной временной меткой и текущим временем и уменьшаете значение hp на основе этого. Затем обновите TextView из холдинга.

Вы также можете использовать AsyncTask - если значение hpvalue требуется обновлять только при активном приложении.

1 голос
/ 30 сентября 2011

Рассмотрите возможность использования AsyncTask, а не Service.Поскольку вы не можете обновить пользовательский интерфейс в фоновом режиме http://developer.android.com/reference/android/os/AsyncTask.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...