2011-11-18 124 views
6

我正在开发一个android应用程序,并且我有一个启动/暂停特定模拟过程的按钮。在此过程正在运行时,我需要实时输出一些数据。但是当我为模拟创建一个新线程时,我无法从该线程访问视图(让它为TextView),因为它们只能从创建它们的线程访问。另一方面,新线程是必需的,因为否则用户在模拟运行时将无法做任何事情(例如,按其他一些按钮)。在这种情况下创建新服务还需要创建一个新线程。我应该如何解决这个问题?从其他线程访问视图(Android)

+0

你检查出['AsyncTask'(HTTP://开发商.android.com/reference/android/os/AsyncTask.html)类?它是一个实用工具类,可帮助您轻松创建不同的线程并相应地更新UI元素。在这种情况下,您可以使用它的'publishProgress()'和'onProgressUpdate()'方法。 – 2011-11-18 13:30:53

回答

5

您可以处理它在许多方面,

  1. 尝试使用的AsyncTask在此,您后台工作doInBackGround()方法做,你的UI将不会阻止你也可以通过publishProgress()和onProgressUpdate()访问您通过其上下文调用AsyncTask的Activity的视图。

  2. 如果您使用的是简单的线程然后使用处理程序或消息或runOnUiThread可以更新主线程的视图。

但是,in your way I think AsyncTask is best for you.

2

您可以用android.os.Handler来解决问题。 Handler实例绑定到创建它的线程,您可以将Runnables发布给它,并且它将在绑定到的线程中执行它们。例如:

import android.os.Handler; 
import android.widget.TextView; 

public class MyActivity extends Activity { 
    private Handler uiHandler; 
    private TextView simulationStatus; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    ... 
    uiHandler = new Handler(); 
    ... 
    simulationStatus = (TextView) findViewById(R.id.simulationStatus); 
    ... 
    } 

    // This method is to be executed on the simulation thread. 
    public void simulate() { 
    ... 
    final String simulationStatusText = ...; 
    ... 
    uiHandler.post(new Runnable() { 
     @Override 
     public void run() { 
     // This is run on the UI thread. 
     simulationStatus.setText(simulationStatusText); 
     ... 
     } 
    }); 
    } 

    ... 
} 

您也可以使用AsyncTask。例如查看链接。

1

将活动传递到您的线程,并从内部使用它来访问您的视图。

// from your activity: 
myExternalThread = new MyCustomCode(this); // <-- activity passed 

// your "simulation process" constructor: 
public MyCustomCode(Activity parent) { 
    this.parent = parent; 
} 

// and when you want to access views: 
parent.runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
     parent.findViewById(R.id.text_view); 
     ... do something to your UI ... 
    } 
}); 

我创建这些外部任务的首选方法是使用AsyncTask(那么你不必担心runOnUiThread,还有其他好处)。我不知道它是否适用于你的案件,但你应该检查出来。

+0

为什么是-1?任何解释? – Guillaume

1

你必须存储你是想确实显示为公共变种,让你的主题通过Handler.post(可运行) 在运行的代码中调用一个Runnable数据()方法可以访问文本视图

2

它们可以被访问但只能是只读的。你的意思是你想触发视图上线程的变化。在工作线程(非UI)中,这些更改无法触发,您需要使用.runOnUiThread()或使用Handlers。点在哪里,你想展示的东西,如更新.runOnUiThread()TextView的使用这些,

例子:

myThread = new Thread() 
     { 

      @Override 
      public void run() { 
       //yourOperation 
       MyActivity.this.runOnUiThread(new Runnable(){ 

        @Override 
        public void run() { 
         if(e!=null) 
         { 
          myTextView.setText("something"); 
         } 

        }}); 
       super.run(); 
      } 
     }; 
     myThread.start(); 
+0

是否真的有可能只读取非ui线程中的视图?我感兴趣的是使用位图drawingCache = view.getDrawingCache()从视图中读取位图,但我不断收到异常:CalledFromWrongThreadException:只有创建视图层次结构的原始线程可以触及其视图。 – Giorgio