赞
踩
最近在做疫情防控APP开发,其中用到了 OWIN Auth2 远程登录认证
结果在通过HttpURLConnection post 请求的时候发现,在Activity 调用网络请求获取认证状态access_token 的时候发现,报了异常,
android.os.NetworkOnMainThreadException,提示网络请求不能在主线程上运行,查阅资料发现,原来从android 4 开始,不允许进行耗时操作,需要重新开辟子线程。解决方案有两个。
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());
}
这种方法会禁用线程安全和内存泄漏及耗时操作检查,生产模式下慎用。
下面这种解决方案是官方推荐,符合线程回调和界面流畅度体验。
网络请求使用开辟主线程上的子线程执行,执行完毕通过主线程处理数据。注意这句话,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();
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。