从错误的线程中调用异常 [英] Calling from wrong thread exception

查看:181
本文介绍了从错误的线程中调用异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想开发一个应用程序,使用线程来实现幻灯片。我从检索SQLite的图像路径​​和ImageView的显示它们。这个问题,在这里我得到了袭击是,我糊涂了,所以我是无法理解的,从哪个线程我打电话图像()方法,在这里我实际执行幻灯片。

我得到了logcat的如下 -

  09-03 13:47:00.248:E / AndroidRuntime(10642):致命异常:螺纹151
09-03 13:47:00.248:E / AndroidRuntime(10642):android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次可以触摸其观点原来的线程。
09-03 13:47:00.248:E / AndroidRuntime(10642):在android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5908)

09-03 13:47:00.248:E / AndroidRuntime(10642):在com.example.fromstart.MainActivity.images(MainActivity.java:90)
09-03 13:47:00.248:E / AndroidRuntime(10642):在com.example.fromstart.MainActivity $ 2.运行(MainActivity.java:59)
09-03 13:47:00.248:E / AndroidRuntime(10642):在java.lang.Thread.run(Thread.java:841)
 

MainActivity.java:

 公共类MainActivity扩展活动
{
    ImageView的jpgView;
    TextView的电视;

    //适配器mDbAdapter;
    适配器信息=新的适配器(本);
    字符串路径;
    处理器smHandler =新的处理程序()
    {
        公共无效的handleMessage(信息MSG)
        {
            TextView的myTextView =
            (TextView中)findViewById(R.id.textView1);
            myTextView.setText(按钮pressed);
        }
    };
    @覆盖
    保护无效的onCreate(包savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_main);
        jpgView =(ImageView的)findViewById(R.id.imageView1);
        电视=(TextView中)findViewById(R.id.textView1);
    }
    @覆盖
    公共布尔onCreateOptionsMenu(菜单菜单)
    {
        //充气菜单;这增加了项目操作栏,如果它是present。
        。getMenuInflater()膨胀(R.menu.main,菜单);


        最终的可运行可运行=新的Runnable()
        {
                 公共无效的run()
                 {
                            图像();
                 }
        };
        INT延迟= 1000; //延迟1秒。
        INT期= 15000; //重复每4秒。
        定时器定时=新的Timer();
        timer.scheduleAtFixedRate(新的TimerTask()
        {
            公共无效的run()
            {
                smHandler.post(可运行);
            }
        },延迟,周期);
        螺纹mythread =新主题(可运行);
        mythread.start();
        返回true;
}
        公共无效的handleMessage(信息MSG)
        {
            串串=样本;
            TextView的myTextView =(TextView中)findViewById(R.id.textView1);
            myTextView.setText(串);
        }
        公共无效图像()
        {
            尝试
            {
                 的for(int i = 0; I< = 20;我++)
                {
                     PATH = info.getpath();
                点阵位图= BitmapFactory.de codeFILE(路径);
                jpgView.setImageBitmap(位);

                }
            }
            赶上(NullPointerException异常ER)
            {
                串HT = er.toString();
                Toast.makeText(getApplicationContext(),HT,Toast.LENGTH_LONG).show();
            }
         }
    }
 

我是新手到Android,刚刚开始工作的主题。如果你发现我的code任何错误,请指出这些问题和建议,请我的,正确的方式来处理这个问题。

在此先感谢。

更新:

 公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.activity_main);
    最终的处理程序mHandler =新的处理程序();

    //创建可运行的发布
    runOnUiThread(新的Runnable()
    {
        公共无效的run()
        {
            图像();
        }
    });
    INT延迟= 1000; //延迟1秒。
    INT期= 15000; //重复每4秒。
    定时器定时=新的Timer();
    timer.scheduleAtFixedRate(新的TimerTask()
    {
        公共无效的run()
        {
            图像();
        }
    },延迟,周期);




}

公共无效图像()
{
    尝试
    {

    Toast.makeText(getApplicationContext(),1,Toast.LENGTH_LONG).show();
             PATH = info.getpath();
             Toast.makeText(getApplicationContext(),2,Toast.LENGTH_LONG).show();
        点阵位图= BitmapFactory.de codeFILE(路径);
        Toast.makeText(getApplicationContext(),3,Toast.LENGTH_LONG).show();
        jpgView.setImageBitmap(位);
        Toast.makeText(getApplicationContext(),4,Toast.LENGTH_LONG).show();

    }
    赶上(NullPointerException异常ER)
   {
            串HT = er.toString();
            Toast.makeText(getApplicationContext(),HT,Toast.LENGTH_LONG).show();
    }
     }

}
 

解决方案

您不能从一个线程更新/访问用户界面。

您有这样的

 公共无效的run()
     {
           图像();
     }
 

和图像中有

  jpgView.setImageBitmap(位);
 

您需要使用 runOnUiThread 更新用户界面。

  runOnUiThread(新的Runnable(){

                    @覆盖
                    公共无效的run(){
                      // 做一点事
                    }
                });
 

TimerTask的也运行在不同的线程。所以,你必须使用一个处理程序updati UI。

您可以使用一个处理程序。

编辑:

 处理程序m_handler;
可运行m_handlerTask;
m_handler =新的处理程序();
m_handlerTask =新的Runnable()
{
  @覆盖
  公共无效的run(){

    // 干点什么。调用图像()
    m_handler.postDelayed(m_handlerTask,1000);

  }
  };
 m_handlerTask.run();
 

如果您仍然希望使用一个计时器任务使用 runOnUiThread

  timer.scheduleAtFixedRate(新的TimerTask()
    {
        公共无效的run()
        {
              runOnUiThread(新的Runnable(){

                    @覆盖
                    公共无效的run(){
                      图像();
                    }
                });

        }
    },延迟,周期);
 

I am trying to develop an application, that uses threads to implement slideshow. I am retrieving the image path from SQLite and displaying them on the ImageView. The problem, where I got struck is, I got confused and so I am unable to understand, from which thread I am calling images() method, where I am actually implementing the slideshow.

I got the Logcat as follows -

    09-03 13:47:00.248: E/AndroidRuntime(10642): FATAL EXCEPTION: Thread-151
09-03 13:47:00.248: E/AndroidRuntime(10642): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
09-03 13:47:00.248: E/AndroidRuntime(10642):    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5908)

09-03 13:47:00.248: E/AndroidRuntime(10642):    at com.example.fromstart.MainActivity.images(MainActivity.java:90)
09-03 13:47:00.248: E/AndroidRuntime(10642):    at com.example.fromstart.MainActivity$2.run(MainActivity.java:59)
09-03 13:47:00.248: E/AndroidRuntime(10642):    at java.lang.Thread.run(Thread.java:841)

MainActivity.java:

public class MainActivity extends Activity
{
    ImageView jpgView;
    TextView tv;

    //adapter mDbAdapter;   
    adapter info = new adapter(this);
    String path; 
    Handler smHandler = new Handler() 
    {
        public void handleMessage(Message msg) 
        {
            TextView myTextView = 
            (TextView)findViewById(R.id.textView1);
            myTextView.setText("Button Pressed");
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        jpgView = (ImageView)findViewById(R.id.imageView1);
        tv = (TextView) findViewById(R.id.textView1);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
    { 
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);


        final Runnable runnable = new Runnable() 
        {
                 public void run() 
                 {
                            images();
                 }
        };
        int delay = 1000; // delay for 1 sec.
        int period = 15000; // repeat every 4 sec.
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() 
        {
            public void run() 
            {
                smHandler.post(runnable);
            }
        }, delay, period);
        Thread mythread = new Thread(runnable);
        mythread.start();
        return true;
}
        public void handleMessage(Message msg) 
        {             
            String string = "sample";
            TextView myTextView = (TextView)findViewById(R.id.textView1);
            myTextView.setText(string);
        }
        public void images()
        {
            try
            {
                 for(int i=0;i<=20;i++)
                {
                     path = info.getpath();
                Bitmap bitmap = BitmapFactory.decodeFile(path);
                jpgView.setImageBitmap(bitmap);

                }
            }
            catch(NullPointerException er)
            {
                String ht=er.toString();
                Toast.makeText(getApplicationContext(), ht, Toast.LENGTH_LONG).show();
            }
         }
    }

I am a newbie to android, just now started working on Threads. If you find any mistakes in my code, please point out those and please suggest me, the right way to deal with this problem.

Thanks in advance.

UPDATE:

 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final Handler mHandler = new Handler();

    // Create runnable for posting
    runOnUiThread(new Runnable() 
    {
        public void run() 
        {
            images();
        }
    });
    int delay = 1000; // delay for 1 sec.
    int period = 15000; // repeat every 4 sec.
    Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() 
    {
        public void run() 
        {
            images();
        }
    }, delay, period);




}

public void images()
{
    try
    {

    Toast.makeText(getApplicationContext(), "1", Toast.LENGTH_LONG).show();
             path = info.getpath(); 
             Toast.makeText(getApplicationContext(), "2", Toast.LENGTH_LONG).show();
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        Toast.makeText(getApplicationContext(), "3", Toast.LENGTH_LONG).show();
        jpgView.setImageBitmap(bitmap);
        Toast.makeText(getApplicationContext(), "4", Toast.LENGTH_LONG).show();

    }
    catch(NullPointerException er) 
   {
            String ht=er.toString();
            Toast.makeText(getApplicationContext(), ht, Toast.LENGTH_LONG).show();
    }
     }

}

解决方案

You cannot update/access ui from from a thread.

You have this

     public void run() 
     {
           images();
     }

And in images you have

    jpgView.setImageBitmap(bitmap);

You need to use runOnUiThread for updating ui.

    runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                      // do something
                    }
                });

TimerTask also runs on a different thread. So you have use a Handler for updati ui.

You can use a handler.

Edit:

Handler m_handler;
Runnable m_handlerTask ;  
m_handler = new Handler();   
m_handlerTask = new Runnable()
{
  @Override 
  public void run() { 

    // do something. call images() 
    m_handler.postDelayed(m_handlerTask, 1000);    

  }
  };
 m_handlerTask.run();

If you still wish to use a timer task use runOnUiThread

timer.scheduleAtFixedRate(new TimerTask() 
    {
        public void run() 
        {
              runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                      images();
                    }
                }); 

        }
    }, delay, period);

这篇关于从错误的线程中调用异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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