在非UI线程上实例化视图

时间:2012-06-26 20:18:22

标签: java android android-asynctask android-ui android-view

我知道UI元素(视图层次结构)可能只能从UI线程中操作。对于后台操作,可以使用AsyncTask,它提供事件处理程序以访问UI线程。

简而言之,是否允许在非UI线程中实例化视图(绑定到getApplicationContext())?此自定义View后代 - 一旦实例化 - 将从 UI线程添加到视图层次结构中。所以只有构造函数调用是在Asynctask.doInBackground()内完成的;它附加(addView(...))到Activity的根布局层次结构仍然在UI线程中完成。

详情:

public MyView extends View {
     public MyView(Context context) { 
            ...
     }
...
}
  1. 我制作了自定义视图,覆盖了onDraw(...)等。

  2. 当用户点击我的主Activity中的某个MenuItem时,会创建另一个Activity(MyOtherActivity)并显示哪个屏幕正好是MyView

  3. 由于MyOtherActivity的屏幕必须立即显示,我在AsyncTask中预先实例化MyView,而用户在主Activity中的其他位置(即他还没有点击那个MenuItem)。 MyView引用存储在静态数据成员中。

  4. 调用MyOtherActivity.onCreate()时,其构造函数代码从静态获取MyView,并通过addView(...)将其添加到其布局根层次结构中。

  5. (我知道静态变量可能会引入内存泄漏,所以一旦不需要,我就将其设置为null。)

  6. MyView是否在其他线程中实例化(并在其构造函数中获取getApplicationContext()的返回值)是不是问题(可能会引入意外问题)?

2 个答案:

答案 0 :(得分:3)

明确的答案出现在View的文档中,标题为“事件处理和线程”:

  

注意:整个视图树是单线程的。在任何视图上调用任何方法时,您必须始终位于UI线程上。 如果您正在处理其他线程并希望从该线程更新视图的状态,则应使用Handler

所以这不仅仅是明显影响用户界面外观的因素,例如addView(),而是“任何任何视图”

任何方法。

@CommonsWare链接到的discussion on android-developers有来自Android框架团队的多名高级工程师,确认要认真对待。

答案 1 :(得分:0)

这是一个示例,介绍如何使用AsyncTask

将视图添加到FrameLayout
public void addFLview(View view) {
    MyAsyncTask as = new MyAsyncTask();
    as.execute(view);
}

AsyncTask类

private class MyAsyncTask extends AsyncTask<View, Void, View> {
    @Override
    protected View doInBackground(View... params) {
        return params[0];
    }
    @Override
    protected void onPostExecute(View view) {
        super.onPostExecute(view);
        myFrameLayout.addView(view);
    }
}