我刚刚编写了一个代码,它添加了几个视图,每个视图使用一个处理程序。这些是使用for循环添加的。这些添加正确。然后我尝试在for循环之后添加一个按钮而不使用处理程序。这次按钮显示在布局的顶部,即在for循环中添加的项目之前。如果我使用处理程序添加按钮,则不会发生这种情况。
因此,如果我在循环后使用以下代码和处理程序,那么按钮将添加到布局的底部:
private void fillFeedWithData(final List<ParseObject> feedObjectList) {
LayoutInflater inflaterOfFeedItem = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for (int i = 0; i < feedObjectList.size(); i++) {
final String jokeTitle = feedObjectList.get(i).getString("content");
final View cvFeedItem = inflaterOfFeedItem.inflate(R.layout.feed_item_theme_card, null);
final TextView tvJoke = (TextView) cvFeedItem.findViewById(R.id.tvFeedJoke);
Handler h2 = new Handler();
Runnable update2 = new Runnable() {
public void run() {
tvJoke.setText(jokeTitle);
llFragmentFeedParent.addView(cvFeedItem);
// llFragmentFeedParent is acquired in OnCreate() method
}
};
h2.post(update2);
}
final Button bNext = new Button(this);
bNext.setText("Next >");
bNext.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
Handler h3 = new Handler();
Runnable update3 = new Runnable() {
public void run() {
llFragmentFeedParent.addView(bNext);
}
};
h3.post(update3);
}
如果我在循环后使用了以下代码,那么按钮将添加到布局的顶部:
Button bNext = new Button(this);
bNext.setText("Next >");
bNext.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
llFragmentFeedParent.addView(bNext);
所以现在我的应用程序正在与处理程序一起工作,但我担心为什么会发生这种情况。我认为处理程序正在混合执行的时间/顺序?如果我继续使用逻辑,那么按钮可能会在慢速移动电话中显示在循环中,甚至在循环中添加的项目之间?
答案 0 :(得分:2)
我不确定你为什么要这样做,但要回答你的问题。处理程序将Runnables发布到按顺序运行的队列中(假设您不使用postDelayed
)。它们最终运行 意味着它们执行时完全取决于发布了多少其他Runnables以及这些Runnables执行所需的时间。
处理程序实际上共享一个创建它们的Looper
线程(在本例中是主UI Looper线程),因此无论您使用多少个Handler引用,它们都将在同一个线程中发布。同样,您可以传入另一个线程的Looper
对象,以便Runnables将在该线程上运行。
在这种情况下,当您添加一个没有处理程序的按钮时,您将在其他处理程序执行之前将其添加到视图 now 。当您在另一个也在UI线程上创建的处理程序中发布时,它会在您发布的第一个处理程序之后将Runnable发布到队列中。所以他们有效地顺序运行。
编辑:
同样在这种情况下,我会完全抛弃Handler
机制,只需将您要添加的所有视图添加到List
中,然后将它们添加到集合中。你每次传递都会发布一个新的Runnable,它将为布局添加一个新视图,这将触发布局传递,这将触发绘制传递。最好一次性添加它们。