学而实习之 不亦乐乎

Android:NetworkOnMainThreadException异常

2020-12-20 09:17:21

看名字就应该知道,是网络请求在MainThread中产生的异常

从3.0开始,google不再允许网络请求(HTTP、Socket)等相关操作直接在Main Thread类中,其实本来就不应该这样做,直接在UI线程进行网络操作,会阻塞UI,导致用户体验较差。

解决办法

1.Handler消息机制

和network有关比较耗时的操作放到一个子线程里,然后用Handler消息机制与主线程通信

public void onCreate(Bundle savedInstanceState) { 
 super.onCreate(savedInstanceState); 
 this.setContentView(R.layout.test);   
 new Thread(new Runnable() {
  @Override
  public void run() {
   // TODO 
   // 在这里进行 http request.网络请求相关操作 
   Message msg = new Message();
   Bundle data = new Bundle();
   data.putString("value", "请求结果");
   msg.setData(data);
   handler.sendMessage(msg);
  }
 }).start();  // 开启一个子线程,进行网络操作,等待有返回结果,使用handler通知UI
} 
 
Handler handler = new Handler() { 
 @Override 
 public void handleMessage(Message msg) { 
  super.handleMessage(msg); 
  Bundle data = msg.getData(); 
  String val = data.getString("value"); 
  Log.i("mylog", "请求结果为-->" + val); 
  // TODO 
  // UI界面的更新等相关操作 
 } 
}; 

2.AsyncTask

使用异步机制,如:asynctask,这个举个简单的加载网络图片的例子

class DownImage extends AsyncTask { 
 
 private ImageView imageView; 
 
 public DownImage(ImageView imageView) { 
  this.imageView = imageView; 
 } 
 
 @Override 
 protected Bitmap doInBackground(String... params) { 
  String url = params[0]; 
  Bitmap bitmap = null; 
  try { 
   //加载一个网络图片 
   InputStream is = new URL(url).openStream(); 
   bitmap = BitmapFactory.decodeStream(is); 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
  return bitmap; 
 } 
 
 @Override 
 protected void onPostExecute(Bitmap result) { 
  imageView.setImageBitmap(result); 
 } 
}

3,直接在主线程中进行网络操作

在发起Http请求的Activity里面的onCreate函数里面添加如下代码(未测试):

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() 
  .detectDiskReads().detectDiskWrites().detectNetwork() 
  .penaltyLog().build()); 
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() 
  .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() 
  .penaltyLog().penaltyDeath().build());