mvd*_*vds 24 java multithreading android runnable
在现有的Android项目中,我遇到了以下代码(我插入了调试垃圾)
ImageView img = null;
public void onCreate(...) {
img = (ImageView)findViewById(R.id.image);
new Thread() {
public void run() {
final Bitmap bmp = BitmapFactory.decodeFile("/sdcard/someImage.jpg");
System.out.println("bitmap: "+bmp.toString()+" img: "+img.toString());
if ( !img.post(new Runnable() {
public void run() {
System.out.println("setting bitmap...");
img.setImageBitmap(bmp);
System.out.println("bitmap set.");
}
}) ) System.out.println("Runnable won't run!");
System.out.println("runnable posted");
}
}.start();
Run Code Online (Sandbox Code Playgroud)
Android开发的新手,并且已经开始搜索,我知道这是在不阻塞主(UI)线程的情况下执行操作的方法,同时仍然在解码后在UI线程上设置图像.(至少根据android-developers)(我已通过Thread.currentThread().getName()在各个地方登录验证)
现在有时图像不会出现,stdout只说
I/System.out( 8066): bitmap: android.graphics.Bitmap@432f3ee8 img: android.widget.ImageView@4339d698
I/System.out( 8066): runnable posted
Run Code Online (Sandbox Code Playgroud)
没有来自Runnable的消息的痕迹.所以看起来Runnable没有run(),尽管img.post()返回true.拉入ImageView onCreate()并声明它final并没有帮助.
我很无能为力.简单地设置位图,同时阻止UI线程,确实可以解决问题,但我想把事情弄清楚.有谁知道这里发生了什么?
(ps.这是在Android 1.6手机和android-3 sdk上观察到的)
kab*_*uko 56
如果您查看文档中View.post有相关信息:
仅当此视图附加到窗口时,才能从UI线程外部调用此方法.
既然你正在这样做onCreate,很可能有时你View的窗户还没有附在窗户上.您可以通过覆盖onAttachedToWindow并在日志中放置内容并在发布时进行日志记录来验证这一点.您会看到,当帖子失败时,之前的帖子就会发生onAttachedToWindow.
正如其他人所提到的,您可以使用Activity.runOnUiThread或提供自己的处理程序.但是,如果你想直接从它View自己做,你可以简单地得到View的处理程序:
view.getHandler().post(...);
Run Code Online (Sandbox Code Playgroud)
如果您有一个包含某种背景加载的自定义视图,这将特别有用.还有一个额外的好处,就是不必创建新的单独处理程序.
Nik*_*Nik 10
我扩展了ImageView课程来解决这个问题.我收集传递给post的runnables,而没有附加到窗口的视图和onAttachedToWindowpost收集的runnable.
public class ImageView extends android.widget.ImageView
{
List<Runnable> postQueue = new ArrayList<Runnable>();
boolean attached;
public ImageView(Context context)
{
super(context);
}
public ImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ImageView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
protected void onAttachedToWindow()
{
super.onAttachedToWindow();
attached = true;
for (Iterator<Runnable> posts = postQueue.iterator(); posts.hasNext();)
{
super.post(posts.next());
posts.remove();
}
}
@Override
protected void onDetachedFromWindow()
{
attached = false;
super.onDetachedFromWindow();
}
@Override
public boolean post(Runnable action)
{
if (attached) return super.post(action);
else postQueue.add(action);
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
我认为问题是你是用一个单独的线程更新UI(ImageView),而不是UI线程.UI只能由UI线程更新.
您可以使用Handler解决此问题:
Handler uiHandler;
public void onCreate(){
...
uiHandler = new Handler(); // This makes the handler attached to UI Thread
...
}
Run Code Online (Sandbox Code Playgroud)
然后替换你的:
if ( !img.post(new Runnable() {
Run Code Online (Sandbox Code Playgroud)
同
uiHandler.post(new Runnable() {
Run Code Online (Sandbox Code Playgroud)
确保在UI线程中更新imageview.
处理程序是一个相当混乱的概念,我也花了几个小时的研究来真正理解这个;)
我没有看到你在那里有什么明显的错误; 调用View.post()应该使它在UI线程上运行.如果您的Activity消失了(可能是通过屏幕旋转),那么您的ImageView将不会更新,但我仍然期望一个日志条目说"设置位图...",即使您看不到它.
我建议尝试以下内容,看看它是否有所作为:
1)使用Log.d(标准Android记录器)而不是System.out
2)将Runnable传递给Activity.runOnUiThread()而不是View.post()
| 归档时间: |
|
| 查看次数: |
18541 次 |
| 最近记录: |