在 android 中发现处理程序的这种奇怪行为
Found this strange behaviour of Handlers in android
我刚刚编写了一段代码,其中添加了多个视图,每个视图都使用一个处理程序。这些是使用 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);
所以现在我的应用程序可以按预期与处理程序一起工作,但我很担心为什么会这样。我认为处理程序混淆了 timings/sequence 执行?如果我继续使用逻辑,按钮是否有可能在慢速移动设备 phone 中出现在循环中添加的项目的顶部甚至之间?
我不确定你为什么要这样做,但回答你的问题。处理程序 post 队列中的可运行对象 运行(假设您不使用 postDelayed
)。它们 运行 最终 意味着它们何时执行完全取决于有多少其他 Runnables posted 以及这些 Runnables 执行需要多长时间。
处理程序实际上共享一个创建它们的 Looper
线程(在本例中是 Main UI Looper 线程),因此无论您引用多少处理程序,它们都会 post 在同一个线程中。同样,您可以传入另一个线程的 Looper
对象,这样 Runnables 将在该线程上 运行。
在这种情况下,当您添加一个没有处理程序的按钮时,您将在其他处理程序执行之前现在将其添加到视图中。当您 post 在另一个处理程序中时,它也是在 UI 线程上创建的,它将 post 在您 post 编辑的第一个队列中的 Runnable。所以他们有效地 运行 按顺序。
编辑:
同样在这种情况下,我会完全放弃 Handler
机制,只将所有要添加的视图放在 List
中,然后将它们添加到集合中。您在每次通过时 post 创建一个新的 Runnable,这将向布局添加一个新视图,这将触发布局通道,这将触发绘制通道。最好一次添加它们。
我刚刚编写了一段代码,其中添加了多个视图,每个视图都使用一个处理程序。这些是使用 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);
所以现在我的应用程序可以按预期与处理程序一起工作,但我很担心为什么会这样。我认为处理程序混淆了 timings/sequence 执行?如果我继续使用逻辑,按钮是否有可能在慢速移动设备 phone 中出现在循环中添加的项目的顶部甚至之间?
我不确定你为什么要这样做,但回答你的问题。处理程序 post 队列中的可运行对象 运行(假设您不使用 postDelayed
)。它们 运行 最终 意味着它们何时执行完全取决于有多少其他 Runnables posted 以及这些 Runnables 执行需要多长时间。
处理程序实际上共享一个创建它们的 Looper
线程(在本例中是 Main UI Looper 线程),因此无论您引用多少处理程序,它们都会 post 在同一个线程中。同样,您可以传入另一个线程的 Looper
对象,这样 Runnables 将在该线程上 运行。
在这种情况下,当您添加一个没有处理程序的按钮时,您将在其他处理程序执行之前现在将其添加到视图中。当您 post 在另一个处理程序中时,它也是在 UI 线程上创建的,它将 post 在您 post 编辑的第一个队列中的 Runnable。所以他们有效地 运行 按顺序。
编辑:
同样在这种情况下,我会完全放弃 Handler
机制,只将所有要添加的视图放在 List
中,然后将它们添加到集合中。您在每次通过时 post 创建一个新的 Runnable,这将向布局添加一个新视图,这将触发布局通道,这将触发绘制通道。最好一次添加它们。