不能从另一个线程触摸视图,怎么可能? [英] cannot touch view from another thread, how to make it possible?
问题描述
我无法弄清楚,为什么我不能设置文本到我的TextView的电视。
越来越:
E / AndroidRuntime(686):$ android.view.ViewRoot CalledFromWrongThreadException:
只有创建一个视图层次可以触摸其观点原来的线程。
我尝试过很多办法来弥补。
正如你可以看到我试着处理程序,因为我曾与敬酒同样的问题。现在,敬酒的作品,但的setText犯规:((
请帮助我的人,我应该如何配置这个处理程序?
公共类计算扩展活动实现OnClickListener {
私人为myService为myService; //绑定服务实例
私人布尔serviceStarted;
查看show_map;
查看数据;
查看启动;
查看停止;
公众的TextView的电视;
私人位置禄;
私人布尔发起= FALSE;
私人浮动距离= 0;
UIHandler uiHandler;
route_calc RC;公共无效的onCreate(捆绑savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.calculate);
电视=(的TextView)findViewById(R.id.textView1);
show_map = findViewById(R.id.button1);
show_map.setOnClickListener(本);
数据= findViewById(R.id.button2);
data.setOnClickListener(本);
开始= findViewById(R.id.button3);
start.setOnClickListener(本);
停止= findViewById(R.id.button4);
stop.setVisibility(View.INVISIBLE);
stop.setOnClickListener(本);
HandlerThread uiThread =新HandlerThread(UIHandler);
uiThread.start();
uiHandler =新UIHandler(uiThread.getLooper());}公共无效的onDestroy(){
super.onDestroy();
}
@覆盖
公共无效的onClick(视图v){
我的意图;
开关(v.getId()){
案例R.id.button1:
I =新意图(这一点,Map.class);
startActivity(ⅰ);
打破;
案例R.id.button2:
I =新意图(这一点,data.class);
startActivity(ⅰ);
打破;
案例R.id.button3:
startService(); 打破;
案例R.id.button4:
stopService();
打破;
}}//这个活动和服务为myService之间的连接
ServiceConnection myServConn =新ServiceConnection(){
@覆盖
公共无效onServiceDisconnected(组件名称为arg0){
为myService = NULL;
}
@覆盖
公共无效onServiceConnected(组件名称为arg0,粘结剂的IBinder){
为myService =((myService.MyBinder)粘合剂).getMyService();
}
};私人无效startService(){
意向意图=新意图(这一点,myService.class);
startService(意向);
//绑定为MyService这里
bindService(意向,myServConn,BIND_AUTO_CREATE);
stop.setVisibility(View.VISIBLE);
serviceStarted = TRUE;
RC =新route_calc();
rc.start();
}私人无效stopService(){
如果(serviceStarted){
意向意图=新意图(这一点,myService.class);
//取消绑定为MyService这里
unbindService(myServConn);
stopService(意向);
stop.setVisibility(View.INVISIBLE); serviceStarted = FALSE;
}
}无效showToast(String s)将{
handleUIRequest(多个);
}无效的setText(){
handleUISetText();
}类route_calc继承Thread {
位置开始;
公共无效的run(){
浮温度;
而(!启动){
尝试{ LOC = myService.getLocation(); }
赶上(例外五){ } 如果(LOC!= NULL){
开始=禄;
启动= TRUE;
showToast(zadzialalo);
} }
而(真){
LOC = myService.getLocation();
TEMP = begin.distanceTo(LOC);
距离=距离+温度;
tv.setText(przejechales+距离+M);
通信System.err.println(距离);
开始=禄;
尝试{
this.sleep(500);
}赶上(InterruptedException的E){
e.printStackTrace();
} } }}
私人final类UIHandler扩展了Handler
{
公共静态最终诠释DISPLAY_UI_TOAST = 0;
公共静态最终诠释TV_SET_TEXT = 1; 公共UIHandler(活套活套)
{
超(活套);
}
公共无效的handleMessage(消息MSG)
{
开关(msg.what)
{
案例UIHandler.DISPLAY_UI_TOAST:
{
上下文的背景下= getApplicationContext();
吐司T = Toast.makeText(背景下,(串)msg.obj,Toast.LENGTH_LONG);
t.show();
} 案例UIHandler.TV_SET_TEXT:
{ tv.setText(przejechałeś+距离+M);
}
默认:
打破;
}
}
}保护无效handleUIRequest(字符串消息)
{
消息味精= uiHandler.obtainMessage(UIHandler.DISPLAY_UI_TOAST);
msg.obj =消息;
uiHandler.sendMessage(MSG);
}保护无效handleUISetText(){
消息味精= uiHandler.obtainMessage(UIHandler.TV_SET_TEXT);
uiHandler.sendMessage(MSG);
}}
好像你把你的整个活动在这里,而且还包括服务,而你没有尝试缩小你的问题。
在你打电话showToast route_calc线程,这可能是你的问题,你应该从你的处理程序调用showToast(或任何其他UI功能)。
事情是这样的:
您是否想在你的线程什么:
新主题(新的Runnable()
{
@覆盖
公共无效的run()
{
尝试
{
someHeavyStuffHere(); //计算巨头在这里或文件下载。
handler.sendEmptyMessage(SUCCESS);
}
赶上(例外五)
{
handler.sendEmptyMessage(失败);
}
}
})。开始();
当你的数据准备好,告诉处理程序把它放在一个视图,并显示它:
保护处理程序处理程序=新的处理程序()
{
@覆盖
公共无效的handleMessage(消息MSG)
{
如果(msg.what == SUCCESS)
{
setCalculatedDataToaView(); //你从你的线程计算的数据,现在可以在你的一个视图中显示。
}
否则,如果(msg.what ==失败)
{
errorHandlerHere(); //可能是你的祝酒词或任何其他错误处理...
}
}
};
I cant figure out why i cant set text to my textView tv. getting:
E/AndroidRuntime(686): android.view.ViewRoot$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
I tried many ways to make it right. As you can see i tried Handler because i had the same problem with toasts. Now toast works but setText doesnt :(( Please someone help me, how should i configure this handler?
public class calculate extends Activity implements OnClickListener {
private myService myService; //bound service instance
private boolean serviceStarted;
View show_map;
View data;
View start;
View stop;
public TextView tv;
private Location loc;
private boolean initiated=false;
private float distance=0;
UIHandler uiHandler;
route_calc rc;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.calculate);
tv=(TextView)findViewById(R.id.textView1);
show_map=findViewById(R.id.button1);
show_map.setOnClickListener(this);
data=findViewById(R.id.button2);
data.setOnClickListener(this);
start=findViewById(R.id.button3);
start.setOnClickListener(this);
stop=findViewById(R.id.button4);
stop.setVisibility(View.INVISIBLE);
stop.setOnClickListener(this);
HandlerThread uiThread = new HandlerThread("UIHandler");
uiThread.start();
uiHandler = new UIHandler( uiThread.getLooper());
}
public void onDestroy(){
super.onDestroy();
}
@Override
public void onClick(View v) {
Intent i;
switch(v.getId()){
case R.id.button1:
i=new Intent(this,Map.class);
startActivity(i);
break;
case R.id.button2:
i=new Intent(this,data.class);
startActivity(i);
break;
case R.id.button3:
startService();
break;
case R.id.button4:
stopService();
break;
}
}
//connection between this activity and service myService
ServiceConnection myServConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName arg0) {
myService = null;
}
@Override
public void onServiceConnected(ComponentName arg0, IBinder binder) {
myService = ((myService.MyBinder)binder).getMyService();
}
};
private void startService() {
Intent intent = new Intent(this, myService.class);
startService(intent);
//Bind MyService here
bindService(intent, myServConn, BIND_AUTO_CREATE);
stop.setVisibility(View.VISIBLE);
serviceStarted = true;
rc = new route_calc();
rc.start();
}
private void stopService() {
if(serviceStarted) {
Intent intent = new Intent(this, myService.class);
//Unbind MyService here
unbindService(myServConn);
stopService(intent);
stop.setVisibility(View.INVISIBLE);
serviceStarted = false;
}
}
void showToast(String s){
handleUIRequest(s);
}
void setText(){
handleUISetText();
}
class route_calc extends Thread{
Location begin;
public void run() {
float temp;
while(!initiated){
try{
loc=myService.getLocation();
}
catch(Exception e){
}
if(loc!=null){
begin=loc;
initiated=true;
showToast("zadzialalo");
}
}
while(true){
loc=myService.getLocation();
temp=begin.distanceTo(loc);
distance=distance+temp;
tv.setText("przejechales "+distance+" m");
System.err.println(distance);
begin=loc;
try {
this.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private final class UIHandler extends Handler
{
public static final int DISPLAY_UI_TOAST = 0;
public static final int TV_SET_TEXT = 1;
public UIHandler(Looper looper)
{
super(looper);
}
public void handleMessage(Message msg)
{
switch(msg.what)
{
case UIHandler.DISPLAY_UI_TOAST:
{
Context context = getApplicationContext();
Toast t = Toast.makeText(context, (String)msg.obj, Toast.LENGTH_LONG);
t.show();
}
case UIHandler.TV_SET_TEXT:
{
tv.setText("przejechałeś "+distance+" m");
}
default:
break;
}
}
}
protected void handleUIRequest(String message)
{
Message msg = uiHandler.obtainMessage(UIHandler.DISPLAY_UI_TOAST);
msg.obj = message;
uiHandler.sendMessage(msg);
}
protected void handleUISetText(){
Message msg=uiHandler.obtainMessage(UIHandler.TV_SET_TEXT);
uiHandler.sendMessage(msg);
}
}
It seems like you put your entire Activity here, and that it also includes a service, and you didn't try to narrow down your problem.
in your route_calc thread you call showToast, this is probably one of your problems, you should call showToast (or any other UI function) from your Handler.
Something like this:
Do anything you want on your thread:
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
someHeavyStuffHere(); //Big calculations or file download here.
handler.sendEmptyMessage(SUCCESS);
}
catch (Exception e)
{
handler.sendEmptyMessage(FAILURE);
}
}
}).start();
When your data is ready, tell the handler to put it in a view and show it:
protected Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
if (msg.what == SUCCESS)
{
setCalculatedDataToaView(); // the data you calculated from your thread can now be shown in one of your views.
}
else if (msg.what == FAILURE)
{
errorHandlerHere();//could be your toasts or any other error handling...
}
}
};
这篇关于不能从另一个线程触摸视图,怎么可能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!