android 线程执行方法吗,android - 从另一个线程在主线程中运行代码

android - 从另一个线程在主线程中运行代码

在android服务中,我创建了一些用于执行某些后台任务的线程。

我有一种情况,线程需要在主线程的消息队列上发布某些任务,例如Handler。

有没有办法获得主线程Handler并从我的其他线程发布Message/Runnable?

谢谢,

12个解决方案

525 votes

注意:这个答案引起了很多关注,我需要更新它。 自从原始答案发布以来,@ dzeikei的评论几乎与原始答案一样受到关注。 这里有两种可能的解决方案:

1.如果您的后台线程具有对Context对象的引用:

确保后台工作线程有权访问Context对象(可以是Application上下文或Service上下文)。 然后在后台工作线程中执行此操作:

// Get a handler that can be used to post to the main thread

Handler mainHandler = new Handler(context.getMainLooper());

Runnable myRunnable = new Runnable() {

@Override

public void run() {....} // This is your code

};

mainHandler.post(myRunnable);

2.如果您的后台线程没有(或需要)Context对象

(由@dzeikei建议):

// Get a handler that can be used to post to the main thread

Handler mainHandler = new Handler(Looper.getMainLooper());

Runnable myRunnable = new Runnable() {

@Override

public void run() {....} // This is your code

};

mainHandler.post(myRunnable);

David Wasser answered 2019-02-23T10:57:13Z

121 votes

正如下面的评论者所指出的,这不是服务的一般解决方案,仅适用于从您的活动启动的线程(服务可以是这样的线程,但不是所有这些线程)。关于服务活动沟通的复杂话题,请阅读官方文档的整个服务部分 - 这很复杂,因此理解基础知识是值得的:[http://developer.android.com/guide/components/services.html#Notifications]

以下方法可以在最简单的情况下工作。

如果我理解正确,你需要在应用程序的GUI线程中执行一些代码(不能考虑其他任何称为“主”线程)。为此,有一个方法Activity:

someActivity.runOnUiThread(new Runnable() {

@Override

public void run() {

//Your code to run in GUI thread here

}//public void run() {

});

Doc:[http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29]

希望这是你正在寻找的。

Alexey Vassiliev answered 2019-02-23T10:58:09Z

28 votes

如果您无法访问Context,还有另一种简单的方法。

1)。 从主循环器创建一个处理程序:

Handler uiHandler = new Handler(Looper.getMainLooper());

2)。 实现Runnable接口:

Runnable runnable = new Runnable() { // your code here }

3)。 将Runnable发布到uiHandler:

uiHandler.post(runnable);

这就是全部;-)享受线程的乐趣,但不要忘记同步它们。

tema_man answered 2019-02-23T10:59:03Z

26 votes

如果您在线程中运行代码,例如 延迟一些动作,然后你需要从上下文调用runOnUiThread。 例如,如果您的代码位于MainActivity类内,则使用此:

MainActivity.this.runOnUiThread(new Runnable() {

@Override

public void run() {

myAction();

}

});

如果您的方法可以从main(UI线程)或其他线程调用,则需要检查:

public void myMethod() {

if( Looper.myLooper() == Looper.getMainLooper() ) {

myAction();

}

else {

}

Alexander Volkov answered 2019-02-23T10:59:38Z

12 votes

精简代码块如下:

new Handler(Looper.getMainLooper()).post(new Runnable() {

@Override

public void run() {

// things to do on the main thread

}

});

这不涉及传递Activity引用或Application引用。

Kotlin等效物:

Handler(Looper.getMainLooper()).post(Runnable {

// things to do on the main thread

})

david m lee answered 2019-02-23T11:00:18Z

4 votes

我能想到的一种方法是:

1)让UI绑定到服务。

2)通过注册您的Handler的Binder公开类似下面的方法:

public void registerHandler(Handler handler) {

mHandler = handler;

}

3)在UI线程中,绑定到服务后调用上面的方法:

mBinder.registerHandler(new Handler());

4)使用Service的线程中的处理程序发布您的任务:

mHandler.post(runnable);

Dheeraj V.S. answered 2019-02-23T11:01:13Z

2 votes

TextView是Android中普通java线程的更好选择。

创建一个HandlerThread并启动它

使用HandlerThread的Looper创建一个处理程序:TextView

TextView a HandlerThread任务Handler

与UI线程的通信来自TextView

使用HandlerThread为主线程创建TextView:Handler并覆盖responseHandler方法

其他线程TextView任务(本例中为HandlerThread),电话Handler,电话:responseHandler

此TextView结果调用HandlerThread在Handler。

从TextView获取属性并处理它,更新UI

示例:使用从Web服务接收的数据更新TextView。 由于应在非UI线程上调用Web服务,因此为网络操作创建了HandlerThread。 从Web服务获取内容后,将消息发送到主线程(UI线程)处理程序,Handler将处理消息并更新UI。

示例代码:

HandlerThread handlerThread = new HandlerThread("NetworkOperation");

handlerThread.start();

Handler requestHandler = new Handler(handlerThread.getLooper());

final Handler responseHandler = new Handler(Looper.getMainLooper()) {

@Override

public void handleMessage(Message msg) {

txtView.setText((String) msg.obj);

}

};

Runnable myRunnable = new Runnable() {

@Override

public void run() {

try {

Log.d("Runnable", "Before IO call");

URL page = new URL("http://www.your_web_site.com/fetchData.jsp");

StringBuffer text = new StringBuffer();

HttpURLConnection conn = (HttpURLConnection) page.openConnection();

conn.connect();

InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());

BufferedReader buff = new BufferedReader(in);

String line;

while ((line = buff.readLine()) != null) {

text.append(line + "\n");

}

Log.d("Runnable", "After IO call:"+ text.toString());

Message msg = new Message();

msg.obj = text.toString();

responseHandler.sendMessage(msg);

} catch (Exception err) {

err.printStackTrace();

}

}

};

requestHandler.post(myRunnable);

有用的文章:

handlerthreads和 - 为什么 - 你 - 应该待使用了他们,在你的Android的应用程序

Android的尺蠖处理程序,handlerthread-I

Ravindra babu answered 2019-02-23T11:03:08Z

1 votes

按照这种方法。 使用这种方式,您只需从后台线程更新UI。 runOnUiThread在主(UI)线程上工作。 我认为这段代码片段不那么复杂和简单,特别是对于初学者。

AsyncTask.execute(new Runnable() {

@Override

public void run() {

//code you want to run on the background

someCode();

//the code you want to run on main thread

MainActivity.this.runOnUiThread(new Runnable() {

public void run() {

/*the code you want to run after the background operation otherwise they will executed earlier and give you an error*/

executeAfterOperation();

}

});

}

});

在服务的情况下

在oncreate中创建一个处理程序

handler = new Handler();

然后像这样使用它

private void runOnUiThread(Runnable runnable) {

handler.post(runnable);

}

MarGin answered 2019-02-23T11:03:54Z

1 votes

我知道这是一个老问题,但我遇到了一个主线程单线程,我在Kotlin和Java中都使用过。 这可能不是服务的最佳解决方案,但是为了调用会改变片段内部UI的内容,这非常简单明了。

Java(8):

getActivity().runOnUiThread(()->{

//your main thread code

});

科特林:

this.runOnUiThread(()->{

//your main thread code

});

mevdev answered 2019-02-23T11:04:30Z

0 votes

public void mainWork() {

new Handler(Looper.getMainLooper()).post(new Runnable() {

@Override

public void run() {

//Add Your Code Here

}

});

}

这也可以在没有问题的服务类中工作。

NUSKTECsoft answered 2019-02-23T11:04:58Z

0 votes

对于Kotlin,你可以使用Anko协同程序:

更新

doAsync {

...

}

弃用

async(UI) {

// Code run on UI thread

// Use ref() instead of this@MyActivity

}

Francis answered 2019-02-23T11:05:36Z

0 votes

最简单的方法,特别是如果你没有上下文,如果你使用RxAndroid,你可以这样做:

AndroidSchedulers.mainThread().scheduleDirect {

runCodeHere()

}

Inn0vative1 answered 2019-02-23T11:06:04Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值