Android:x秒后多次更新gridview

时间:2012-01-20 21:08:48

标签: java android ui-thread

我每隔x秒就在android中更新视图时遇到问题。

要了解android是如何工作的,我正在写一个小游戏。 它有一个GameController,可以保存游戏循环。在循环内部,逻辑被执行,之后gui将被告知变化。

问题是在视图中无法看到更改。视图保持不变,直到游戏循环结束,然后只更新一次。

这是我的代码(重要部分):

GameController.java:

IGui gui;

public void play() {
    while (playing) {
        getAndProcessInput();
        updateGui();
        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
        }
    }
}

private void updateGui() {
    gui.setPlayer(x, y);
    // ...
}

GameActivity.java:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    GridView gridview = (GridView) findViewById(R.id.GridView1);
    TextAdapter = new TextAdapter(this);
    gridview.setAdapter(textAdapter);

    GameController c = new GameController();

    // here, the game loop shoud start.
    // what i tried:

    // new Thread(c).start();   <-- causes crash

    // c.play();     <-- causes view to frease until game loop is done

    this.runOnUiThread(c);  <-- causes view to frease until game loop is done
}

TextAdapter.java:

public class TextAdapter extends BaseAdapter implements IGui {

    private final Context context;
    private final String[] texts;

    public TextAdapter(Context context) {
        this.context = context;
        texts = new String[height * width];
        for (int i = 0; i < texts.length; i++) {
            texts[i] = " ";
        }
    }

    public int getCount() {
        return height * width;
    }

    public Object getItem(int position) {
        return null;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        TextView tv;
        if (convertView == null) {
            tv = new TextView(context);
            tv.setLayoutParams(new GridView.LayoutParams(25, 25));
        } else {
            tv = (TextView) convertView;
        }

        tv.setText(texts[position]);
        return tv; // <-- this happens only when game loop is done, not everytime something changed
    }

    @Override 
    public void setPlayer(int x, int y) {
        texts[width * y + x] = "X";
        // this.notifyDataSetChanged();  <-- this does not help (view still freases) 
        //                                   gridview.invalidateViews(); does not help either
    }
}

我搜索了很多并尝试了很多(我知道这里曾经问过类似的问题,但他们也没有帮助我),但不知何故它只是不起作用。 我无法让它在视图和逻辑运行在android中的不同theads上工作,如果它们在同一个线程上运行,则逻辑阻止视图。 任何帮助将不胜感激。

//编辑:

如果我尝试新的线程(c).start(); LogCat sais: java.lang.RuntimeException:无法在未调用Looper.prepare()的线程内创建处理程序

如果我添加Looper.prepare(); : java.lang.RuntimeException:无法启动活动ComponentInfo {GameActivity}:java.lang.RuntimeException:每个线程只能创建一个Looper

如果我试试这个.runOnUiThread(c);没有错误。

3 个答案:

答案 0 :(得分:2)

首先,这似乎不是游戏的方式,你需要使用SurfaceViewGLSurfaceView来更好地做你想要的。 你也可以在Android上寻找Cocos2d,它是一个2D平台(从iPhone移植而来),让你的生活更轻松: http://code.google.com/p/cocos2d-android/ 我冥想警告你,我几个月前尝试过它,它还没有生产等级,它确实不时崩溃。

无论如何,如果您仍想继续前进,我会尝试回答您的问题: 我认为你对这些东西应该起作用的方式太过分了。首先尝试理解处理程序如何使用线程。

在你的帖子上做任何你想要的事情:

   new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        calculateGameChangesHere();
                        handler.sendEmptyMessage(SUCCESS);
                    }
                    catch (Exception e)
                    {
                        handler.sendEmptyMessage(FAILURE);
                    }
                }
            }).start();

当您的数据准备就绪后,告诉处理程序将其放在视图中并显示它:

protected Handler handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            if (msg.what == SUCCESS)
            {
                setCalculatedDataToaView(); // the data you calculated from your thread can now be shown in one of your views.
            }
            else if (msg.what == FAILURE)
            {
                errorHandlerHere();//could be your toasts or any other error handling...
            }
        }
    };

这适用于需要大量处理/网络的所有内容,不应阻止您的UI线程。

希望这有帮助。

答案 1 :(得分:0)

通过每隔几秒刷新listView,不确定您要实现的目标。无论如何,如果您正在编写一些2D游戏,您必须使用SurfaceView,这尤其适用于持续刷新。

答案 2 :(得分:0)

遇到同样的问题并使用非常简单的代码解决了它。

提示:

  • 必须由UI线程刷新GridView
  • 要显示每个更改,您必须使循环和Sleep方法远离UI线程


解决方案:

  • 更新网格的方法(在第一个地方或任何地方放置构建GridView的Activity)

    public void UpdateGrid(){
    //your logic
    
    //your way to change grid values (there are tones of other ways)
    CustomGridAdapter cga = new CustomGridAdapter(this, values);
    
    gridView.setAdapter(cga);
    gridView.invalidateViews();
    

    }

  • 构建完成工作的非UI线程

公共类DataReceiver实现Runnable {

private MainActivity mainActivity;

public DataReceiver(MainActivity ma) {
    mainActivity = ma;
}

@Override
public void run() {

    for (int i = 0; i < 100; i++) {

        mainActivity.runOnUiThread(new Runnable() {
            public void run() {
                                   //update the grid here
                mainActivity.UpdateGrid();

            }
        });
                      //sleep here
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

}