【问题标题】:updating TextView in a Runnable causes Activity stop在 Runnable 中更新 TextView 会导致 Activity 停止
【发布时间】:2014-04-10 15:38:08
【问题描述】:

我有一个媒体播放器服务,其中我有一个 Runnable,它每 100 毫秒更新一次搜索栏和当前位置 TextView

private Runnable mUpdateTimeTask = new Runnable() {
        public void run() {
            long totalDuration = mediaPlayer.getDuration();
            long currentDuration = mediaPlayer.getCurrentPosition();

           seekBar.setProgress(progress);
           nowduration.setText("" + utils.milliSecondsToTimer(currentDuration));
           totalduration.setText(""+utils.milliSecondsToTimer(totalDuration));

            // Running this thread after 100 milliseconds
            mHandler.postDelayed(this, 100);
        }
    };

问题是,一段时间(5-10 秒)后活动停止,我在 logcat 中看到的唯一错误就是这个。虽然删除 nowduration.setText 一切正常,但 seekbar 更新没有任何问题,为什么 TextView 活动停止?

04-10 10:22:40.610      288-813/system_process I/ActivityManager﹕ Process com.package.appname (pid 3734) has died.
04-10 10:22:40.610     288-3633/system_process I/WindowManager﹕ WIN DEATH: Window{424b5708 com.package.appname/com.package.appname.MainActivity paused=false}

我尝试过:1. 在 TextView.setText 上使用 runOnUithread - 相同的行为 2. 使用线程而不是处理程序 - 但我在停止线程时遇到问题,有时我需要调用 Handler.removeCallBacks,但据我所知,停止thread 是一个非常糟糕的操作,这就是 Thread.stop( 被贬低的原因。

【问题讨论】:

标签: java android runnable


【解决方案1】:

UserInterface 只能由 UI 线程更新。您需要一个处理程序,以发布到 UI 线程:

private void startTimerThread() {
Handler handler = new Handler();
Runnable runnable = new Runnable() {
    private long startTime = System.currentTimeMillis();
    public void run() {

            try {
                Thread.sleep(1000);
            }    
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.post(new Runnable(){
                public void run() {
        long totalDuration = mediaPlayer.getDuration();
        long currentDuration = mediaPlayer.getCurrentPosition();

       seekBar.setProgress(progress);
       nowduration.setText("" + utils.milliSecondsToTimer(currentDuration));
       totalduration.setText(""+utils.milliSecondsToTimer(totalDuration));


            }
        });
        }

};
new Thread(runnable).start();
}

【讨论】:

  • 我在 op 的代码中没有看到后台线程。 Op 正在使用处理程序。 mHandler.postDelayed(this, 100);。如果您在 ui 线程中创建一个处理程序,则它与该处理程序相关联。引用 当你创建一个新的 Handler 时,它会绑定到创建它的线程的线程/消息队列——从那时起,它会将消息和可运行对象传递到该消息队列并在它们到来时执行它们退出消息队列。
  • 嗯...看起来像Android OS Bug...也许这篇文章可以帮助你stackoverflow.com/a/17955940/1145140
【解决方案2】:

尝试使用 Handler 消息来做到这一点:

private Handler handler = new Handler(){

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg); 

        switch(msg.what){
            case 1:{
                long totalDuration = mediaPlayer.getDuration();
                long currentDuration = mediaPlayer.getCurrentPosition();

                seekBar.setProgress(progress);
                nowduration.setText("" + utils.milliSecondsToTimer(currentDuration));
                totalduration.setText(""+utils.milliSecondsToTimer(totalDuration));

                // Running this thread after 100 milliseconds
                mHandler.sendEmptyMessageDelayed(1, 100);
            }break;
        }
    }

};

第一次更新开始:

...
handler.sendEmptyMessage(1);
...

【讨论】:

  • 我不知道为什么,但这给了我与我的代码相同的行为。活动刚刚结束。我认为这是内存泄漏,但不知道为什么。可能是我的手机出了点问题?
  • 您的播放器是否在错误原因之前完成播放?
  • 不,活动停止,媒体播放器服务也停止。问题出在 textView 中,因为在删除 TextView.setText() 时,您的代码可以正常工作。
猜你喜欢
  • 1970-01-01
  • 2012-09-24
  • 2020-01-28
  • 1970-01-01
  • 1970-01-01
  • 2015-11-11
  • 2014-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多