【问题标题】:Android Thread modify EditTextAndroid Thread 修改 EditText
【发布时间】:2011-10-25 02:02:31
【问题描述】:

我在线程启动的另一个函数中修改 EditText 时遇到问题:

Thread thRead = new Thread( new Runnable(){
    public void run(){
       EditText _txtArea = (EditText) findViewById(R.id.txtArea);
       startReading(_txtArea);
    }
 });

我的功能如下:

public void startReading(EditText _txtArea){
         _txtArea.setText("Changed");
}

它总是在尝试修改编辑文本时强制关闭。有人知道为什么吗?

【问题讨论】:

    标签: java android multithreading android-edittext


    【解决方案1】:

    不应从非 UI 线程修改 UI 视图。唯一可以接触 UI 视图的线程是“主”或“UI”线程,即调用onCreate()onStop() 和其他类似组件生命周期函数的线程。

    因此,每当您的应用程序尝试从非 UI 线程修改 UI 视图时,Android 都会提前抛出异常以警告您这是不允许的。那是因为 UI 不是线程安全的,而这样的预警实际上是一个很棒的功能。


    更新:

    您可以使用Activity.runOnUiThread() 更新用户界面。或使用AsyncTask。但由于您的情况需要不断地从蓝牙读取数据,因此不应使用AsyncTask

    这是runOnUiThread() 的示例:

    runOnUiThread(new Runnable() {            
        @Override
        public void run() {
            //this will run on UI thread, so its safe to modify UI views.
             _txtArea.setText("Changed");
        }
    });
    

    【讨论】:

    • 我认为这是有道理的。我的问题是我正在编写一个程序,该程序不断地从蓝牙读取数据并将从缓冲区获得的数据打印到编辑文本框中。连续阅读是在一个线程中完成的。你对我如何输出结果有什么建议吗?
    • 感谢您的帮助。我将如何编写该代码来使用我的代码?抱歉,我是线程新手... Thread thRead = new runOnUiThread(new Runnable() { 等... 可以吗?
    • runOnUiThread 是否真的比 asynctask 性能更高?
    【解决方案2】:

    首先查看您的日志,它通常包含应用关闭时的堆栈跟踪。

    你不应该像往常一样运行线程,而是使用runOnUiThread

    Runnable thRead = new Runnable(){
       public void run() {
          EditText _txtArea = (EditText) findViewById(R.id.txtArea);
          startReading(_txtArea);
       }
    };
    runOnUiThread(thRead);
    

    说明:只允许UI线程改变UI组件的状态。

    【讨论】:

    • 这停止了强制关闭,但是 Edittext 上没有任何改变(因为没有文本出现)可能是因为它是一个不同的实例?
    • 我应该做点别的吗?
    • 堆栈跟踪会有所帮助。假设 findViewById 实际上返回了一些有用的东西。如果您使用单独的组件运行它,它可能为空。由于您已经接受了另一个答案,因此您不需要发布堆栈跟踪;)另外请注意: Handler 类对此也很有用,但线程总是容易出现并发错误等。
    【解决方案3】:

    这篇文章可能会对你有所帮助。

    http://android-developers.blogspot.com/2009/05/painless-threading.html

    有几个选项:
    1. 在 UI 线程上运行它Activity.runOnUiThread(Runnable)
    2.使用AsyncTask

    【讨论】:

      【解决方案4】:

      除了runOnUiThread()(有效),还有另一种方法,我知道:

      在你的 UI (Activity) 类中定义一个处理程序:

      public class MainActivity extends Activity {
      
      .....
      
          Handler uiThreadHandler = new Handler() {
              public void handleMessage(Message msg) {
                  Object o = msg.obj;
                  if (o==null) o = "";
                  TextView textIn = (TextView)findViewById(R.id.textin);
                  textIn.setText(o.toString());
              }
          };
      
      }
      

      您可以从某个线程内部调用它:

      Message msg = uiThreadHandler.obtainMessage();
      msg.obj = "Text for EditView";
      uiThreadHandler.sendMessage(msg);
      

      【讨论】:

        【解决方案5】:

        默认情况下,主线程是 UI 线程。所有修改应用程序外观的代码都需要在这个线程中运行。如果您想在应用程序中有多个线程可以修改 UI,我建议您使用 AsyncTask 类。

        public someMethod(){
            new ChangeTextTask().execute();
        }
        
        private class ChangeTextTask extends AsyncTask<Void, Void, Void> {
            @Override
            protected Void doInBackground(Void... params) {
                startReading(_txtArea);
                return null;
            }
        }
        

        但是,您需要采取措施防止多个线程同时访问 EditText 对象。否则你会得到一个 CurrentModificationException 错误。

        http://developer.android.com/reference/android/os/AsyncTask.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-09-09
          • 1970-01-01
          • 2018-09-22
          • 1970-01-01
          • 2014-11-08
          • 2021-12-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多