2

我试图找出线程并遇到这个问题,如果应用程序被发送到后面,TextView 会停止更新,然后再恢复。

如何确保应用程序重新回到前面后 TextView 继续更新?

或者...

重新启动活动后,如何将 TextView 重新连接到我的可运行线程中的处理程序?

有一个进度条可以正常工作,所以我有点困惑。我很感激一些建议,因为我认为我可能犯了一个简单的错误。

public class ThreadTestActivity extends Activity {
    private Handler handler;
    private static ProgressBar progress;
    private TextView tv;
    private int counter = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ThreadTest);
        handler = new Handler();
        progress = (ProgressBar) findViewById(R.id.progressBar1);
        tv = (TextView) findViewById(R.id.myText);
        Button but = (Button) findViewById(R.id.Button01);

        but.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

                thread_fun();
            });}
    }
    private void thread_fun() {

        new Thread(new Runnable() {
            public void run() {

                try {
                    while (counter < 100) {
                        counter += 20;
                        Thread.sleep(2000);
                        // Update the progress bar and TextView (in 5 chunks of 20, 0 to 100) 
                        // This works perfectly it the app stays in front
                        handler.post(new Runnable() {
                            public void run() {
                            // but after sending to the back (esc) and bringing the activity back to the front
                                progress.setProgress(counter); //This progres bar maintains its value and updates correctly
                                tv.setText(String.valueOf(counter)); //This TextView reverts to its default text and does not update  
                            }
                        });
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}
4

1 回答 1

1

当一个活动在后台运行然后恢复时,它会经历整个生命周期。这意味着创建了一个新实例,并再次调用 Activity.onCreate。有关详细信息,请参见此处的图表。需要注意的重要一点是,活动经历了这个生命周期,并且在方向改变时也会被销毁和重新创建。所以这是你必须意识到并与之合作或围绕的事情。

当您的 Activity 在后台运行并恢复时更新 ProgressBar 的原因是您在每次调用 onCreate 时设置的 Activity 中有一个静态引用。此静态引用在您的 Activity 的第一个实例和您恢复后创建的第二个实例之间共享。一旦你开始你的线程,它只会更新这个引用指向的任何 ProgressBar,所以你会得到同一个 ProgressBar 正在更新的印象。

事实上,它不是同一个对象,它是一个不同的实例。这就是为什么 TextView 中的文本没有更新的原因,因为线程正在更新一个较旧的 TextView 实例,而不是屏幕上的那个。您可以在调试器中确认所有这些,或者更简单地通过打印出对象的哈希码来确认。尝试将其放入您的 while 循环中:

Log.d("thread_fun", "threadid="+Thread.currentThread().getId()+
    ",progressbar="+progress.hashCode()+
    ",textview="+tv.hashCode());

请注意,ProgressBar 的哈希码发生了变化,因为线程正在更新一个新的 ProgressBar,但正在更新的 TextView 的哈希码没有变化。

D/thread_fun(28989): thread=3483,progress=1097438768,textview=1097437160
D/thread_fun(28989): thread=3483,progress=1097438768,textview=1097437160
D/thread_fun(28989): thread=3483,progress=1097528568,textview=1097437160
D/thread_fun(28989): thread=3483,progress=1097528568,textview=1097437160

现在,答案不是让 TextView 也是静态的。这不是您应该在 Activity 生命周期更改之间维护状态的方式,因为如果您不小心,它可能会导致内存泄漏,坦率地说,这也令人困惑,正如您从上面看到的那样。相反,您应该覆盖其他生命周期方法之一,onPause 或 onStop,以保存 ProgressBar 和 TextView 的状态,并可能终止正在更新它的线程。然后,在 onCreate 中,您需要将该状态从 Bundle 中拉出,并将 ProgressBar 和 TextView 恢复到用户离开时的状态,并且还可能重新启动线程。您可能想要阅读的方法称为Activity.onSaveInstanceState. 还有其他选项,但这是 StackOverflow 在很多问题中都涉及的内容,并且在 Android SDK 文档中进行了很好的描述。

我希望这会有所帮助!如果不清楚,请告诉我!

于 2012-09-15T03:38:37.390 回答