不能从另一个线程触摸视图,怎么可能? [英] cannot touch view from another thread, how to make it possible?

查看:263
本文介绍了不能从另一个线程触摸视图,怎么可能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法弄清楚,为什么我不能设置文本到我的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆