简单来说,业务当时的界面是有两种输入登录模式,其中密码登录模式有三个EditText还有一个显示验证码的ImageView(用Bitmap动态加载图片),然后手机号登录模式中只有两个EditText。
我在代码中通过传入的值来切换模式的切换,具体类似下面的代码。
private void initMode() {
clearAnimation();
switch (mode){
case Login.LOGIN_PASSWORD:
etLoginArea.setVisibility(View.GONE);
etLoginPhone.setVisibility(View.GONE);
etLoginAccount.setVisibility(View.VISIBLE);
llLoginPassword.setVisibility(View.VISIBLE);
llLoginValidCode.setVisibility(View.VISIBLE);
getValidCode(); //通过网络获取验证码
btnLogin.setEnabled(false);
break;
case Login.LOGIN_PHONE:
etLoginAccount.setVisibility(View.GONE);
llLoginPassword.setVisibility(View.GONE);
llLoginValidCode.setVisibility(View.GONE);
etLoginArea.setVisibility(View.VISIBLE);
etLoginPhone.setVisibility(View.VISIBLE);
btnLogin.setEnabled(false);
break;
}
}
private void clearAnimation() {
etLoginAccount.clearAnimation();
llLoginPassword.clearAnimation();
llLoginValidCode.clearAnimation();
etLoginArea.clearAnimation();
etLoginPhone.clearAnimation();
btnLogin.clearAnimation();
}
然后在界面中出现了错误。
具体错误表现为:
我的解决措施:
在三个方法都没有显著效果之后,我开始精准调参数,来定位到底是哪个控件出现问题,最后定位到时ImageView中加载bitmap时,才会出现之前的错误。
public void showValidCode(Bitmap bitmap) {
try {
//获取网络图片成功后调用这一行,其中ivLoginValidCode是llLoginValidCode内部的一个ImageView
ivLoginValidCode.setImageBitmap(bitmap);
}catch (Exception e){
e.printStackTrace();
}
}
在第一次加载bitmap时会出现错误日志:
2019-12-13 11:50:12.071 10658-10818/com.sys.washmashine W/System.err: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
2019-12-13 11:50:12.071 10658-10818/com.sys.washmashine W/System.err: at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7753)
2019-12-13 11:50:12.071 10658-10818/com.sys.washmashine W/System.err: at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1225)
2019-12-13 11:50:12.071 10658-10818/com.sys.washmashine W/System.err: at android.view.View.requestLayout(View.java:23093)
2019-12-13 11:50:12.072 10658-10818/com.sys.washmashine I/chatty: uid=10254(com.sys.washmashine) identical 8 lines
2019-12-13 11:50:12.072 10658-10818/com.sys.washmashine W/System.err: at android.view.View.requestLayout(View.java:23093)
2019-12-13 11:50:12.072 10658-10818/com.sys.washmashine W/System.err: at android.widget.ImageView.setImageDrawable(ImageView.java:571)
2019-12-13 11:50:12.072 10658-10818/com.sys.washmashine W/System.err: at android.support.v7.widget.AppCompatImageView.setImageDrawable(AppCompatImageView.java:100)
2019-12-13 11:50:12.072 10658-10818/com.sys.washmashine W/System.err: at android.widget.ImageView.setImageBitmap(ImageView.java:705)
2019-12-13 11:50:12.072 10658-10818/com.sys.washmashine W/System.err: at android.support.v7.widget.AppCompatImageView.setImageBitmap(AppCompatImageView.java:108)
结果发现是传统的非主线程不能修改ui的错误。
然后才发现当时在申请图片的post接口中是new Thread().run()执行的。结果申请之后并没有通过handler到主线程再加载。最终就出了这个错误。
public void getValidCodeCode(String uuid) {
final String path = ("xxx" + uuid); //地址不是原先的地址
new Thread() {
public void run() {
try {
HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
conn.setConnectTimeout(30 * 1000);
conn.setRequestMethod("POST");
InputStream inputStream = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
showValidCode(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
但是实际上只有在第一次执行setImageView的时候,才会报错,后面执行的时候是不会报错的。也就是说其实子线程是可以执行Imageview.setImageBitmap这行代码。
所以我猜测出错的原因是在一部分手机上出现了线程不同步的错误,才导致了这个问题。
最后为了解决这个问题,用上了只有一个线程的线程池来节约反复打开线程的消耗问题。
因篇幅问题不能全部显示,请点此查看更多更全内容