notifyDataSetChanged只刷新GridView一次,尽管被多次调用



我将尝试如下总结我的代码:

  • 我有一个TileAdapter从BaseAdapter扩展到填充GridView
  • My TileAdapter包含一个tile数组,用于维护状态
  • 我的TileUpdate类执行以下操作:
    1. 将Tile A的颜色更改为绿色
    2. 调用TileAdapter.notifyDataSetChanged ()
    3. 将Tile B的颜色改为黄色
    4. 调用TileAdapter.notifyDataSetChanged ()
    5. 将Tile B的颜色更改为红色
    6. 调用TileAdapter.notifyDataSetChanged ()

我本来希望看到我的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提供一个新的任务对象。这个想法是,任务的处理将在一个单独的线程上执行,并在它完成后调用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

为什么任务还在主线程上运行?

我假设您在onClick方法中进行了所有这些更改。onClick方法在UI线程中运行…因此,当onClick中的代码正在运行时,UI线程不能更改和平铺颜色,因为它很忙。事实上,notifyDataSetChanged只是设置了一个标志,告诉Android在它可以时更新对视图的更改;notifyDataSetChanged不强制更新,但简单地告诉android一个需要。因此,你只是告诉android它需要更新视图三次…但是,在你的onClick方法完成之后,android实际上可以进行更新,它只能看到最近的瓷砖颜色变化。

你怎么解决这个问题?嗯,这取决于你真正想做什么。例如,如果您希望在单击视图时将颜色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);

你应该看看从计时器更新UI。问题是,当您调用notifyDataSetChanged()时,您只会触发GUI的标志。当适配器获得重新绘制时,它检查是否设置了标志并采取行动。当你调用notify时,不直接采取任何动作。

如果你想直接更新GUI,你应该了解类Handler(见前面的链接),这样你就可以发布更新到接口。

也许我误解了你的问题,但似乎你正在更新两倍的颜色Tile B(相同的步骤3和5在你的问题)。如果是这种情况,您将只看到最后一种颜色(红色),当然,黄色将永远不会显示。

或者,你指的是步骤5中的"Tile C"。如果是这种情况,那么下面的注释可能会有所帮助:

即使UI改变了3次,你也可能在每次调用中重写每种颜色。

1)所以你的三个贴图是'默认'颜色

2)你将贴图A更新为绿色

3) notifyDataSetChanged()调用

(你的网格视图更新正确)

4)你将Tile B更新为黄色

5) notifyDataSetChanged()被调用

(你的网格视图更新标题B为黄色,但覆盖标题A为'默认'颜色。

6)你将C块更新为红色

7) notifyDataSetChanged()被调用

(你的网格视图更新标题C为红色,但覆盖标题A和B为'默认'的颜色。

这可能就是问题所在。

另外,请记住,正如其他人提到的,notifyDataSetChanged()不直接做任何事情。它仅在满足理想条件时才通知UI刷新。

最新更新