我将尝试按如下方式汇总我的代码:
我希望看到我的GridView刷新3次,每次调用notifyDataSetChanged()一次。
但是,我只看到它在第6步之后刷新,当时并且从未看到Tile B变黄。
这里发生了什么?我认为有一些我不知道的API。
由于
更新
即使在研究了下面描述的Handler方法之后,我仍未成功实现这一点。 所以在我的UI线程中,我创建了一个新的GridOperationQueue类,它从Thread:
扩展而来public class GridOperationQueue extends Thread {
private Handler handler;
@Override
public void run() {
Looper.prepare();
handler = new Handler();
Looper.loop();
}
public void addTaskToQueue(final GridUpdateTask task)
{
Log.d(this.getClass().toString(), "Current thread is ID " + Thread.currentThread().getId());
handler.post(new Runnable()
{
@Override
public void run() {
Log.d(this.getClass().toString(), " Handler task's current thread is ID " + Thread.currentThread().getId());
task.run();
}
});
}
public void clearQueue(){
handler.removeCallbacksAndMessages(null);
}
}
所以我的UI线程调用addTaskToQueue提供一个新的Task对象。我们的想法是,任务的处理将在一个单独的线程上执行,并在完成后在UI线程上调用notifyDataSetChanged()。 但是,我添加了一些日志记录,似乎当我的任务运行时,它们仍然在主线程上运行......这将是什么?请参阅以下日志记录:
GridOperationQueue(4393): Current thread is ID 1
GridOperationQueue(4393): Current thread is ID 1
GridOperationQueue(4393): Current thread is ID 1
GridOperationQueue$1(4393): Handler task's current thread is ID 9
TileOperationService$1(4393): Current thread is ID 9
MyActivity(4393): Current thread is ID 9
GridOperationQueue$1(4393): Handler task's current thread is ID 9
TileOperationService$2(4393): Current thread is ID 9
MyActivity(4393): Current thread is ID 9
GridOperationQueue$1(4393): Handler task's current thread is ID 9
TileOperationService$3(4393): Current thread is ID 9
MyActivity(4393): Current thread is ID 9
为什么任务仍然在主线程上运行?
答案 0 :(得分:2)
我假设您在onClick方法中进行了所有这些更改。 onClick方法在UI线程中运行...因此,当onClick中的代码正在运行时,UI线程无法更改并且因为它忙碌而平铺颜色。事实上,notifyDataSetChanged只是设置一个标志,告诉Android更新视图的更改>; notifyDataSetChanged不强制更新,但简单告诉android一个是必需的。因此,你只是告诉android它需要更新视图三次...但是,当android实际上可以进行更新时,这是在你的onClick方法完成之后,它只能看到最近对tile的更改颜色。
你如何解决这个问题?那么,这取决于你真正想做的事情。例如,如果您希望在单击视图时将图块颜色A更改为图块颜色B,然后在500毫秒后更改为图块颜色C,请执行以下操作
Handler handler; // instance var
public onCreate(Bundle savedInstanceState) {
...
handler = new Handler();
}
// in your onClick method, wherever it may be (pseudocode)
public void onClick(View v) {
1) set tile color to color B
2) call notifyDataSetChanged
3) schedule a color change in 500 ms:
handler.postDelayed(new Runnable() {
public void run() {
1) set tile color to color C
2) call notifyDataSetChanged
}
}), 500);
答案 1 :(得分:1)
你应该看看Updating the UI from a Timer。麻烦的是,当你调用notifyDataSetChanged()
时,你只会触发GUI的标志。当适配器获得重绘时,它会检查标志是否已设置并执行操作。当您致电通知时, 不会直接采取任何行动。
如果您想直接更新GUI,您应该了解类Handler(请参阅上一个链接),以便您可以将更新发布到界面。
答案 2 :(得分:0)
也许我误解了你的问题,但似乎你正在更新两次Tile B的颜色(在你的问题上完全相同的步骤3和5)。如果是这种情况,当然只能看到最后一种颜色(红色)和黄色。
或者,您在步骤5中的意思是“Tile C”。如果是这种情况,则以下注释可能有所帮助:
即使用户界面正在改变3次,您也可能会在每次通话时覆盖每种颜色。
1)所以你的三个瓷砖是'默认'颜色
2)您将Tile A更新为绿色
3)调用notifyDataSetChanged()
(您的网格视图已正确更新)
4)您将Tile B更新为黄色
5)调用notifyDataSetChanged()
(您的网格视图会将标题B更新为黄色,但会将标题A更改为“默认”颜色。
6)您将Tile C更新为红色
7)调用notifyDataSetChanged()
(您的网格视图会将标题C更新为红色,但会将标题A和B重写为“默认”颜色。
这可能就是问题所在。
另外,请记住,正如其他人提到的那样,notifyDataSetChanged()没有直接做任何事情。它仅表示在满足理想条件时刷新UI。