4

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

简而言之,是否允许getApplicationContext()在非 UI 线程中实例化视图(绑定到)?这个自定义的 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不需要时。)

getApplicationContext()MyView 在不同的线程中实例化(并在其构造函数中获取返回值)不是一个问题(并且可能会引入意想不到的问题)吗?

4

2 回答 2

5

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

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

所以它不仅仅是明显影响 UI 外观的东西,比如addView(),而是“任何View上的任何方法”。

@CommonsWare 链接到的关于 android-developers的讨论有不止一位来自 Android 框架团队的高级工程师确认这将被认真对待。

于 2012-06-27T00:49:29.623 回答
0

这是一个示例,说明如何使用 AsyncTask 将视图添加到 FrameLayout

public void addFLview(View view) {
    MyAsyncTask as = new MyAsyncTask();
    as.execute(view);
}

异步任务类

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);
    }
}
于 2014-11-06T19:44:05.610 回答