关于android开发中线程安全的问题想必大家都碰到过。

特别是android.os.NetworkOnMainThreadException

在android的不同版本出错误地方是访问网络的webservice有问题。

很多情况下,我们通常是访问网络获取数据,然后根据数据来改变UI的显示。

比如ListView或者TextView,我们获取数据后,需要在这些控件上面显示。

在Android2.3以下的版本中,我们可以直接写流水线的方式,获取数据,给控件赋值,既可以完成。

但是在Android2.3以上的版本(包含2.3)就不能这样写了。

这样写在访问网络时会提示android.os.NetworkOnMainThreadException

在给控件赋值时会提示Only the original thread that created a view hierarchy can touch its views.

这主要是Android的相关View和控件不是线程安全的。


针对这个问题,解决方案有如下几种:

1)用异步任务去解决,开启一个异步进程去进行数据访问与控件赋值。

代码如下:

/**     * 点击登录开线程,出现进度提示框     *      * @author weis     *      */    public class loginTask extends AsyncTask<String, Void, String> {        private Exception _exception = null;        private String errMsg = "";        @Override        protected void onPreExecute() {            loading.show();        }        @Override        protected void onPostExecute(String ss) {            loading.dismiss();            if (null != _exception) {                ToastUtil.show(Login.this, errMsg + _exception.getMessage());            }else{                ToastUtil.show(Login.this, "登录成功!");            }        }        @Override        protected String doInBackground(String... params) {            // TODO Auto-generated method stub            try {                LoginOn();            } catch (UnknownHostException hostExp) {                _exception = hostExp;                errMsg = "找不到服务器:";            } catch (Exception e) {                _exception = e;                errMsg = "登录失败: ";            }            return null;        }    }

2)也是使用线程的方式Thread,不过不是上面的处理方式,而是通过Hander,Runnable 去处理。

  protected void Operation() {    Thread t = new Thread() {public void run() {try {strSchoolYear = semester.getCurrentSemester().getValue();} catch (Exception e) {ToastUtil.show(getBaseContext(), e.getMessage());}handler.post(runnable); }};t.start();}Handler handler = new Handler();Runnable runnable = new Runnable() {public void run() {schoolYearTextView.setText(strSchoolYear);}};

3)在2.3以上版本中先加入了 新的类 StrictMode,用于捕捉发生在应用程序主线程中耗时的磁盘、网络访问或函数调用,可以帮助开发者改进程序,使主线程处理 UI 和动画在磁盘读写和网络操作时变得更平滑,避免主线程被阻塞。

本人比较懒,比较喜欢这种方式

编写一个基类,在基类的OnCreate方法中加入重构StrictModel的代码,就可以继续用以前的流水线的方式编码了。

public void onCreate(Bundle savedInstanceState) {String strVer=android.os.Build.VERSION.RELEASE;//重构StrictModestrVer=strVer.substring(0,3).trim();float fv=Float.valueOf(strVer);if(fv>2.3){StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectAll().build());}super.onCreate(savedInstanceState);}
detectAll 是允许所有操作,包括磁盘访问,网络访问等。

这种方式要谨慎使用。

弊端很明显,在主线程中读取数据,读取磁盘可能比较耗时,容易引起主线程堵塞,用户体验不好。



更多相关文章

  1. Android实现一个通用的PopupWindow
  2. Android(安卓)PullToRefresh下拉刷新控件的简单使用
  3. 转载-runOnUIThread解析
  4. Android(安卓)获取OnItemClick事件中组件的内容
  5. Android周报第四期
  6. 让应用程序具体相应权限
  7. Android(安卓)ANR 详解
  8. Android(安卓)自定义 View - 颜色选取器(水平、竖直)
  9. Android知识体系图

随机推荐

  1. Android(安卓)Activity的启动
  2. Android查看网页源码与开启子线程
  3. Android(安卓)中Layout实现点击水波纹特
  4. Android-->获取所有联系人以及所有的字段
  5. Android(安卓)AsyncTask
  6. android linux 基础知识总结
  7. Android第二个功能:短信发送
  8. Android(安卓)属性系统 详解
  9. Android开发之手机震动器
  10. cocos2d-x-3.1在eclipse中的环境搭建