从另一个类中的线程更新Android UI
我在这里看到了一些类似的问题,但我还没有找到合适的答案。许多人问过如何从线程更新UI,但他们几乎总是和UI在同一个类中 我要做的是从另一个类中创建的线程更新UI。我已经看到了所有的建议,比如异步、处理程序、可运行等等。。。但是我在单独的类中实现它们时遇到了真正的困难 我试图使我的UI类最小化,并且只处理与GUI的交互,例如当用户按下按钮时。现在,我在一个新类中创建了一个新线程,它连接到蓝牙设备,但是我想将UI线程中的一个按钮从“连接”按钮更改为“断开连接”按钮(即,将按钮从创建蓝牙套接字更改为关闭它) 一般的做法是什么?我是否认为这一切都错了,应该把所有的东西都放在一节课上?在“主”UI类和其他类/线程之间进行交互的正确方式是什么从另一个类中的线程更新Android UI,android,multithreading,asynchronous,runnable,handlers,Android,Multithreading,Asynchronous,Runnable,Handlers,我在这里看到了一些类似的问题,但我还没有找到合适的答案。许多人问过如何从线程更新UI,但他们几乎总是和UI在同一个类中 我要做的是从另一个类中创建的线程更新UI。我已经看到了所有的建议,比如异步、处理程序、可运行等等。。。但是我在单独的类中实现它们时遇到了真正的困难 我试图使我的UI类最小化,并且只处理与GUI的交互,例如当用户按下按钮时。现在,我在一个新类中创建了一个新线程,它连接到蓝牙设备,但是我想将UI线程中的一个按钮从“连接”按钮更改为“断开连接”按钮(即,将按钮从创建蓝牙套接字更改为关
理想情况下,我希望能够进行其他UI交互,因此一些允许在UI类之外进行其他UI更改的解决方案将非常棒 使用
runOnUiThread(Runnable)
方法在主线程上运行一些东西,如果它是一个视图,则调用ClassName.View.invalidate()
方法,或者只在你的目标类中创建一个public
方法来处理UI的刷新
我试图做的是从一个已经被更新的线程更新UI
在另一个类中创建。我已经看到了所有的建议,比如
异步、处理程序、可运行等。。。但我遇到了真正的麻烦
在单独的类中实现它们
一般来说,对于您的目标,我建议您使用:
- 与
活动中它作为独立类(es)而不是内部类(es),那么我建议使用构造函数来传递上下文、小部件,通常是任何您想要的,然后以正确的方法(允许UI更新)更新您的UI
我这样做是因为我喜欢干净的类(所以UI类只有UI实现,逻辑是分开定位的)
例子:
有两种选择。如果您有权访问正在更改的视图,并且只需要强制刷新,则可以从任何线程使用View.postInvalidate()
。如果需要更复杂的操作,例如更改按钮的文本,则应使用runOnUIThread
,这需要访问活动
上下文。这应该很容易获取-只需将其作为自定义对象构造函数的参数添加即可。在这种情况下,您可以执行以下操作:
activityContext.runOnUiThread(new Runnable(){
@Override
public void run() {
myButton.setText("disconnect");
}
});
谢谢你。我想到两件事。我曾经尝试过使用AsyncTask和我遇到的各种示例,但是我看到了一些关于它的信息,其中它指出AsyncTask必须在与UI相同的类中调用。这是正确的还是可以在别处调用?其次,我没有像你建议的那样成功地传递上下文。我在主UI线程中创建了一个静态上下文变量,然后尝试在新类中访问它,但没有太长时间。你可能会有一些示例代码,或者知道我在哪里可以找到一些吗?@ritchie888我在这里写了AsyncTask
的示例。那里应该有链接或其他东西吗?因为它没有显示。干杯。@ritchie888不,这里是我专门为你写的例子。单击浏览器中的F5。不,您只能传递数组,简单地说,AsyncTask就是这样指定的(有时您需要从doInBackground传递多个值,有时应用程序逻辑需要它,所以如果AsyncTask只传递单个值,这对于所有可能的情况都是不够的)。doInBackground方法在后台运行(在后台线程中),通常设计用于计算长时间运行的操作,是的,onProgressUpdate是在UI线程上运行的方法,您可以想象它就像后台和UI之间的“方式”。
public class Main extends Activity implements View.OnClickListener {
private Button b;
public void onCreate(Bundle b) {
super.onCreate(b);
// initialise widgets and set listeners to appropriate widgets
}
public void onClick(View v) {
switch(v.getId()) {
case R.id.connectBtn:
startWorker();
break;
}
}
private void startWorker() {
TaskExample te = new TaskExample(this, b);
te.execute();
}
}
activityContext.runOnUiThread(new Runnable(){
@Override
public void run() {
myButton.setText("disconnect");
}
});