2 illegal id illegal_id 于 2016.02.23 00:33 提问

Android线程与ui绘制的问题

当然知道只能在主线程更新UI,不过我有个非常费时的UI绘制操作(就是一堆自定义的view退出时保存在文件里,然后进入时读取文件绘制ui恢复界面,实测短板出现在view的绘制过程)

然后我一开始觉得只要View不添加就只是对象而已,然后尝试新开一个线程把这些控件new出来,然后在主线程addView,结果在我的平板(5.1.1)上完美运行,在手机(4.2.2)上闪退。

继续测试手机,新开一个线程,一个执行一句new一个edittext就崩溃,不过更加奇怪的是换成textview就正常。完全不明就里。

ps,大家有什么替代方法,也望不吝赐教,感激不尽

按照大家的提醒贴代码(实际的代码太长不便理解,我就写了一个TextView和EditText的,意思一样,而且方便大家理解。)

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                new TextView(mActivity);
            } catch (Exception e) {
                Log.d("debug", Log.getStackTraceString(e));
                return;
            }
            Log.d("debug", "成功地new了一个TextView");
            try {
                new EditText(mActivity);
            } catch (Exception e) {
                Log.d("debug", Log.getStackTraceString(e));
                return;
            }
            Log.d("debug", "成功地new了一个EditText");
        }
    }).start();
}

附上Logcat输出:

02-23 03:29:13.144 16364-16440/com.example.multicalc D/debug: 成功地new了一个TextView
02-23 03:29:13.156 16364-16440/com.example.multicalc D/debug: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.(Handler.java:197)
at android.os.Handler.(Handler.java:111)
at android.widget.Editor$UserDictionaryListener.(Editor.java:3836)
at android.widget.Editor.(Editor.java:192)
at android.widget.TextView.createEditorIfNeeded(TextView.java:8475)
at android.widget.TextView.(TextView.java:1114)
at android.widget.EditText.(EditText.java:60)
at android.widget.EditText.(EditText.java:56)
at android.widget.EditText.(EditText.java:52)
at com.example.multicalc.matrix.ui.WorkWindow$1.run(WorkWindow.java:174)
at java.lang.Thread.run(Thread.java:856)

11个回答

wangbaokangfei
wangbaokangfei   2016.02.25 18:04
已采纳

弱引用的方式,防止内存泄漏

caozhy
caozhy   Ds   Rxr 2016.02.23 07:16

先开一个内存Image对象,线程中对它绘图,然后再一次性加载到界面上。

illegal_id
illegal_id 我也是这么做的,可是运行到new就挂了
接近 2 年之前 回复
hyb1996
hyb1996   2016.02.23 08:58

runOnUiThread(new Runnable(){
@Override
public void run() {
//更新UI,new控件
}
}

illegal_id
illegal_id 这确实是可行的,不过我的费事任务是控件的创建和设置,这样在ui线程中跑,和直接单线程其实一样的。违背了问题初衷
接近 2 年之前 回复
illegal_id
illegal_id 这确实是可行的,不过我的费事任务是控件的创建和设置,这样在ui线程中跑,和直接单线程其实一样的。违背了问题初衷
接近 2 年之前 回复
hyb1996
hyb1996   2016.02.23 09:05

直接在线程中addView就好,不然可能出现NullPointerException.

illegal_id
illegal_id 并不是空指针问题,已更新代码,可以看看
接近 2 年之前 回复
wangbaokangfei
wangbaokangfei   2016.02.23 09:24

挂了是报出了什么错误,粘一下错误日志看下...

illegal_id
illegal_id 谢谢提醒,代码日志已贴
接近 2 年之前 回复
liuguangsuiyue
liuguangsuiyue   2016.02.23 11:02

根据日志看什么错误, 不然就只有乱猜

illegal_id
illegal_id 代码和日志已贴,有劳帮忙看看
接近 2 年之前 回复
dongfeng9ge
dongfeng9ge   Ds   Rxr 2016.02.23 20:42

这个在onResume里重写一遍就好了吧

wangbaokangfei
wangbaokangfei   2016.02.25 18:04

弄个内存缓存池,把创建的view缓存下来

u013147734
u013147734   2016.03.18 14:09

线程里new一个view我还是第一次见,new出来的对象又没使用过,这里局部new的view,主线程也拿不到这个变量。你是否要addview呢,一addview必定报错。线程中绘制界面请了解下surfaceview的双缓冲机制。或者简单实现用线程读取数据,完成之后handler通知view更新。
我不知道线程里new view行不行,但是我没听说过

u013147734
u013147734   2016.03.18 14:15

代码报错看来,显然edittext在创建的时候会自动创建handler,这个handler他需要做什么事,也许是用来通知绘制光标的改变等等。这个handler创建的时候在工作线程了,所以报错了。
可以去看下new edittext里面的机制。
我猜,textview在创建的时候不会去new handler所以暂时没报错

共11条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!