在线程里面出现异常需要处理UI的细节

来源:互联网 发布:淘宝如何找人代付 编辑:程序博客网 时间:2024/05/16 15:56
1、错误提示: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
                        at android.widget.Toast$TN.<init>(Toast.java:324)

2、简单说明以下问题,当我们需要在线程里面下载文件或图片时,有时候可能会连接不上网络,或找不到资源,有可能出现异常的问题,这个时候我们需要用一个 Toast 提示我们下载失败,按照常规,我们会在网络下载的地方处理异常捕捉,在 catch 里面使用 Toast ,这个做法是错误的。

看一下代码吧!

启动线程的代码:
  final ProgressDialog dialog = ProgressDialog.show(WelcomeActivity.this,
    "更新文件", "图片下载中,请稍候……");
  new Thread(new Runnable() {
   public void run() {
    if (isNetworkAvailable()) {
     try {
      goImage(); // 调用下载图片的方法
      Thread.sleep(1000);
     } catch (Exception e) {
      dialog.dismiss(); // 捕捉到异常后,把进度条销毁
      Toast.makeText(WelcomeActivity.this, "你下载图片失败", 0).show();
      goMainAty(); // 跳转到主界面
      return; //这里注意:当服务器出现故障的时候,就要跳出run()里面的方法,否则会出致命的错误
     }
    } else {
     Toast.makeText(WelcomeActivity.this, "网络链接出错,请检查网络!", 1) .show(); 
     Log.d("Thread","isNetworkAvailable() error!");
    }
    dialog.dismiss();
    goMainAty(); // 跳转到主界面
   }
  }).start(); // 启动线程

private void goImage() throws Exception {
  MyDB db = new MyDB(WelcomeActivity.this); // 获取自定义的数据库连接类
  Cursor cursor = db.SECELTSQL(InfoBean.find()); // 执行查询语句,得到 Cursor 集合对象
  String[] list = getList(cursor); // 把cursor集合里的所有元素加到 String[]类型数组中
  if (list.length != 0) {
   ThreadLoadImage(list); // 调用线程下载图片的方法
  }else{
   Log.d("WecomeActivity", "下图片的list.size()为空!");
  }
 }

 再看下载图片的方法:
/**
  * @param list 传入的是一个 String 类型的数组
  * @throws Exception
  */
 private void ThreadLoadImage(final String[] list) throws Exception {
  for(int i=0;i<list.length;i++){
     LoadBitmap load = new LoadBitmap(WelcomeActivity.this);
    Bitmap bitmap = load.getBitmap(list[i],String.valueOf(i+1));
    Log.d("WelcomeActivity.java", "LoadBitmap(WelcomeActivity.this) is OK!");
  }
 }

从上面的代码似乎没出现什么问题,但是在运行的时候,要是遇到下载图片的异常的时候就出现问题了,但是测试的时候,我故意把服务器关了,问题就来了


错误是 Toast 在Handler 里面初始化的时候出错,

从这个错误中,我得出一点,就是在线程里,不能在执行UI上的东西,典型的就是我的这个错误,不能显示 Toast , 在很多教材或网上也提到,在线程下载完成不能这里面执行线程 ,解决的方法,是用 Handler 实现UI 的显示;

Handler mhandler = new Handler(){
  public void handleMessage(Message msg){
   if(msg.what == 0x100){
    Toast.makeText(WelcomeActivity.this, "你下载图片失败", 0).show();
   }
  }
 };

在线程里要如下更改:
  final ProgressDialog dialog = ProgressDialog.show(WelcomeActivity.this,
    "更新文件", "图片下载中,请稍候……");
  new Thread(new Runnable() {
   public void run() {
    if (isNetworkAvailable()) {
     try {
      goImage(); // 调用下载图片的方法
      Thread.sleep(1000);
     } catch (Exception e) {
      dialog.dismiss(); // 捕捉到异常后,把进度条销毁
  //    Toast.makeText(WelcomeActivity.this, "你下载图片失败", 0).show();
      Message m = new Message();
      m.what =0x100;
      mhandler.sendMessage(m);
      goMainAty(); // 跳转到主界面
      return; //这里注意:当服务器出现故障的时候,就要跳出run()里面的方法,否则会出致命的错误
     }
    } else {
     Toast.makeText(WelcomeActivity.this, "网络链接出错,请检查网络!", 1) .show(); 
     Log.d("Thread","isNetworkAvailable() error!");
    }
    dialog.dismiss();
    goMainAty(); // 跳转到主界面
   }
  }).start(); // 启动线程

private void goImage() throws Exception {
  MyDB db = new MyDB(WelcomeActivity.this); // 获取自定义的数据库连接类
  Cursor cursor = db.SECELTSQL(InfoBean.find()); // 执行查询语句,得到 Cursor 集合对象
  String[] list = getList(cursor); // 把cursor集合里的所有元素加到 String[]类型数组中
  if (list.length != 0) {
   ThreadLoadImage(list); // 调用线程下载图片的方法
  }else{
   Log.d("WecomeActivity", "下图片的list.size()为空!");
  }
 }

0 0
原创粉丝点击