首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >notifyDataSetChanged只刷新GridView一次,尽管它被多次调用

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

Stack Overflow用户
提问于 2011-11-02 23:57:12
回答 3查看 2.5K关注 0票数 0

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

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

我希望看到我的GridView刷新3次,每次对notifyDataSetChanged()的调用都会刷新一次。

但是,我只看到它在步骤6之后刷新,当和从来没有看到Tile B变黄。

这里发生了什么事?我猜想有一些API是我不知道的。

谢谢

更新

即使在研究了下面描述的Handler方法之后,我仍然没有成功地实现这一点。因此,在我的UI线程中,我创建了一个新的GridOperationQueue类,它扩展自线程:

代码语言:javascript
复制
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()。但是,我已经添加了一些日志记录,当我的任务运行时,它们仍然在主thread....how上运行,这会是吗?请参见以下日志记录:

代码语言:javascript
复制
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

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

EN

回答 3

Stack Overflow用户

发布于 2011-11-03 03:00:06

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

你怎么才能避开这一切?这取决于你到底想做什么。例如,如果单击视图时希望瓷砖颜色A更改为瓷砖颜色B,然后在单击视图后更改为瓷砖颜色C 500 ms,请执行以下操作

代码语言:javascript
复制
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);
票数 2
EN

Stack Overflow用户

发布于 2011-11-03 00:19:53

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

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

票数 1
EN

Stack Overflow用户

发布于 2011-11-03 01:26:13

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

或者,在步骤5中,您的意思是"Tile C“。

即使UI更改了3次,您也可能会在每次调用中重写每个颜色。

1)所以你的三个瓷砖是‘默认’颜色

2)你把地砖A更新成绿色

3)调用notifyDataSetChanged()

(网格视图被正确更新)

4)将Tile B更新为黄色

5)调用notifyDataSetChanged()

(网格视图将标题B更新为黄色,但将标题A重写为“默认”颜色。

6)将Tile C更新为红色

7)调用notifyDataSetChanged()

(网格视图将标题C更新为红色,但将标题A和B重写为“默认”颜色。

这可能就是问题所在。

另外,请记住,正如其他人所提到的,notifyDataSetChanged()不直接做任何事情。它只在满足理想条件时发出刷新UI的信号。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7988819

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档