最近在做疫情防控APP开发,其中用到了 OWIN Auth2 远程登录认证 结果在通过HttpURLConnection post 请求的时候发现,在Activity 调用网络请求获取认证状态access_token 的时候发现,报了异常, android.os.NetworkOnMainThreadException,提示网络请求不能在主线程上运行,查阅资料发现,原来从android 4 开始,不允许进行耗时操作,需要重新开辟子线程。解决方案有两个。 1 就是禁用耗时检查和内存泄漏规则,在网络请求前面添加(Activity)。 if (Build.VERSION.SDK_INT >= 11) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads ().detectDiskWrites().detectNetwork().penaltyLog().build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build()); } 这种方法会禁用线程安全和内存泄漏及耗时操作检查,生产模式下慎用。 2 下面这种解决方案是官方推荐,符合线程回调和界面流畅度体验。 网络请求使用开辟主线程上的子线程执行,执行完毕通过主线程处理数据。注意这句话,c++ 处理界面更新要求有回调函数处理,c# 处理界面更新要求使用背景线程或者委托以及线程回调,android 也一样,其实都是一个原理,就是线程内存共享机制,为了保护线程安全。 首先定义主线程消息处理函数来更新界面,这里是弹了一个tip. private Handler mainHandler = new Handler(Looper.getMainLooper()) { public void handleMessage(android.os.Message msg) { TokenInfo tokenInfo = (TokenInfo) msg.obj; Toast.makeText(LoginActivity.this, tokenInfo.refresh_token, Toast.LENGTH_SHORT).show(); }; }; 然后在请求数据的地方,开辟子线程处理网路请求,然后发送消息到主线程处理函数。 new Thread() { public void run() { try { TokenInfo tokenInfo = (TokenInfo) adminService.AdminLogin(adminInfo); //这里是网络请求 Message msg = mainHandler.obtainMessage(); msg.obj = tokenInfo; mainHandler.sendMessage(msg); //发送主线程处理 } catch (IOException e) { e.printStackTrace(); } } }.start(); |
|Archiver|手机版|小黑屋|软件开发编程门户
( 陇ICP备2024013992号-1|
甘公网安备62090002000130号 )
GMT+8, 2025-3-14 13:46 , Processed in 0.037523 second(s), 17 queries .
Powered by Discuz! X3.5
© 2001-2024 Discuz! Team.