Android主线程不能访问网络异常解决办法

从两个方面说下这个问题:

1. 不让访问网络的原因

2. 解决该问题的办法

不让访问网络的原因:

由于对于网络状况的不可预见性,很有可能在网络访问的时候造成阻塞,那么这样一来我们的主线程UI线程 就会出现假死的现象,产生很不好的用户体验。所以,默认的情况下如果直接在主线程中访问就报出了这个异常,名字是NetworkOnMainThreadException

解决该问题的办法

1. 独立线程

2. 异步线程AsyncTask

3. StrictMode修改默认的策略

1) 独立线程的办法

启动一个新线程的代码:
new Thread(){

@Override

public void run() {

Dosomething();

handler.sendEmptyMessage(0);

}

}.start();

例子:

[java]  view plain copy print ?
  1. public class MainActivity extends Activity {  
  2.   
  3.     private Button btnTest;  
  4.     private Button btnClear;  
  5.     private TextView txtResult;  
  6.     private Handler handler = null;  
  7.   
  8.     @Override  
  9.     protected void onCreate(Bundle savedInstanceState) {  
  10.         // StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()  
  11.         // .detectDiskReads()  
  12.         // .detectDiskWrites()  
  13.         // .detectNetwork() // or .detectAll() for all detectable problems  
  14.         // .penaltyLog()  
  15.         // .build());  
  16.         // StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()  
  17.         // .detectLeakedSqlLiteObjects()  
  18.         // .detectLeakedClosableObjects()  
  19.         // .penaltyLog()  
  20.         // .penaltyDeath()  
  21.         // .build());  
  22.   
  23.         super.onCreate(savedInstanceState);  
  24.         setContentView(R.layout.activity_main);  
  25.         btnTest = (Button) findViewById(R.id.btnTest);  
  26.         btnClear = (Button) findViewById(R.id.btnClear);  
  27.         txtResult = (TextView) findViewById(R.id.txtResult);  
  28.         //  
  29.         handler = new Handler() {  
  30.             public void handleMessage(Message msg) {  
  31.                 super.handleMessage(msg);  
  32.                 if (msg.what == 0) {  
  33.                     txtResult.append("\nBegin test >>\n");  
  34.                 } else if (msg.what == 1) {  
  35.                     txtResult.append(msg.obj.toString());  
  36.                 } else if (msg.what == 2) {  
  37.                     txtResult.append("\n<<End test\n");  
  38.                 }  
  39.             }  
  40.         };  
  41.         //  
  42.         txtResult.setText("");  
  43.         txtResult.setMovementMethod(ScrollingMovementMethod.getInstance());  
  44.   
  45.         btnTest.setOnClickListener(new View.OnClickListener() {  
  46.   
  47.             @Override  
  48.             public void onClick(View v) {  
  49.                 // doTest();  
  50.                 doTestOnAndroid4();  
  51.             }  
  52.         });  
  53.         btnClear.setOnClickListener(new View.OnClickListener() {  
  54.   
  55.             @Override  
  56.             public void onClick(View v) {  
  57.                 doClear();  
  58.   
  59.             }  
  60.         });  
  61.   
  62.     }  
  63.   
  64.     protected void doClear() {  
  65.         txtResult.setText("");  
  66.   
  67.     }  
  68.   
  69.     protected void doTest() {  
  70.   
  71.         String url = "http://www.baidu.com/";  
  72.         txtResult.append("\nBegin test >>\n");  
  73.         String text = "";  
  74.         try {  
  75.             text = Jsoup.connect(url).get().toString();  
  76.         } catch (Exception e) {  
  77.             e.printStackTrace();  
  78.             // text = e.getMessage();  
  79.         }  
  80.         txtResult.append(text);  
  81.         txtResult.append("\n<<End test\n");  
  82.     }  
  83.   
  84.     protected void doTestOnAndroid4() {  
  85.   
  86.         new Thread(new Runnable() {  
  87.             @Override  
  88.             public void run() {  
  89.                 Message m = new Message();  
  90.                 m.what = 0;  
  91.                 handler.sendMessage(m);  
  92.                 //  
  93.                 m = new Message();  
  94.                 m.what = 1;  
  95.                 String url = "http://www.baidu.com/";  
  96.                 try {  
  97.                     m.obj = Jsoup.connect(url).get().toString();  
  98.                 } catch (Exception e) {  
  99.                     e.printStackTrace();  
  100.                     // m.obj = e.getMessage();  
  101.                 }  
  102.                 handler.sendMessage(m);  
  103.                 //  
  104.                 m = new Message();  
  105.                 m.what = 2;  
  106.                 handler.sendMessage(m);  
  107.             }  
  108.         }).start();  
  109.   
  110.     }  
  111.   
  112. }  

此处我们重写了线程类的run方法,执行Dosomething. 在里面还有个handler对象,这又涉及到了跨线程修改UI元素内容的问题。在java中是不允许跨线程修改UI元素的,如我们在新启动的线程中想去修改UI主线程中TextView的文本时,会报错误的。如果想做这样的操作,我们就得借助Handler这个类来实现。 关于这个handler类的用法,我们单独的再来写一篇博客进行介绍。

2) 异步调用的方法 AsyncTask

这里关于AsyncTask 介绍的文章不错, 详细情况看作者的介绍吧  
http://www.cnblogs.com/dawei/archive/2011/04/18/2019903.html#2824345
接下来也将会有一篇博客专门介绍 关于更新主线程UI线程的所有办法

3) StrictMode修改默认的策略

在我们的Activity类的onCreate方法中,设置如下规则:
StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

这样也可以解决这个问题

关于StrictMode的具体介绍,请看另一个博客介绍的非常详细:

http://hb.qq.com/a/20110914/000054.htm

在onCreate中加入以下代码即可:

<span style="font-family: Arial; font-size: 14px; line-height: 26px; background-color: rgb(255, 255, 255);">不过如果要求至少是API-9才可以,否则会编译器提示错误,所以在适配一些低版本系统时候不太给力。</span>
 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 .detectDiskReads()
                 .detectDiskWrites()
                 .detectNetwork()   // or .detectAll() for all detectable problems
                 .penaltyLog()
                 .build());
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                 .detectLeakedSqlLiteObjects()
                 .detectLeakedClosableObjects()
                 .penaltyLog()
                 .penaltyDeath()
                 .build());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

番茄小能手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值