当前位置:   article > 正文

Android中控件setVisibility(View.Gone)失效(经测试是非UI线程导致)_setvisibility(view.gone)

setvisibility(view.gone)
  • 前提:这个错误在Demo中无法展示,因为是实际场景的复杂情况。
  • 场景:只有一部分手机出现。

简单来说,业务当时的界面是有两种输入登录模式,其中密码登录模式有三个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();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

然后在界面中出现了错误。

具体错误表现为:

  1. setVIsibility(View.GONE)的实际效果为setVIsibility(View.INVISIBLE)
  2. setVIsibility(View.VISIBLE)无效
  3. 整个控件的布局没有重新测量宽高。

我的解决措施:

  1. 网络上的clearAnimation方法,加入了无效。
  2. requestLayout()方法,无效。
  3. 在xml文件的相关控件中加入visibility="gone"标签,无效。

在三个方法都没有显著效果之后,我开始精准调参数,来定位到底是哪个控件出现问题,最后定位到时ImageView中加载bitmap时,才会出现之前的错误。

public void showValidCode(Bitmap bitmap) {
    try {
    	//获取网络图片成功后调用这一行,其中ivLoginValidCode是llLoginValidCode内部的一个ImageView
        ivLoginValidCode.setImageBitmap(bitmap);
    }catch (Exception e){
        e.printStackTrace();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在第一次加载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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

结果发现是传统的非主线程不能修改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();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

但是实际上只有在第一次执行setImageView的时候,才会报错,后面执行的时候是不会报错的。也就是说其实子线程是可以执行Imageview.setImageBitmap这行代码。

所以我猜测出错的原因是在一部分手机上出现了线程不同步的错误,才导致了这个问题。

最后为了解决这个问题,用上了只有一个线程的线程池来节约反复打开线程的消耗问题。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/308882
推荐阅读
相关标签
  

闽ICP备14008679号