Android: Updating gridview multiple times after x seconds

风流意气都作罢 提交于 2019-12-11 11:33:35

问题


I am having a problem updating the view in android every x seconds.

To get to know how android works I am writing a small game. It has a GameController which holds the game loop. Inside the loop, the logic is executed and afterwards the gui will be informed about the changes.

The problem is that the changes cannot be seen in the view. The view stays the same until the game loop finishes and updates then only once.

Here is my code (the important parts):

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
    }
}

I googled a lot and tried a lot as well (and I do know that similar questions where asked here already, but they did not help me either), but somehow it just does not work. I cannot get it do work that the view and logic run on different theads in android, and if they run on the same thread the logic blocks the view. Any help would be greatly appreciated.

// edit:

If I try new Thread(c).start(); LogCat sais: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

And if I add Looper.prepare(); : java.lang.RuntimeException: Unable to start activity ComponentInfo{GameActivity}: java.lang.RuntimeException: Only one Looper may be created per thread

If I try this.runOnUiThread(c); there are no errors.


回答1:


First, this doesn't seems like the way to crate a game, you will need to use SurfaceView, or GLSurfaceView to better do what you want. You can also look for Cocos2d for android, it's a 2D platform (that was ported from iPhone) that makes you life easier: http://code.google.com/p/cocos2d-android/ I muse warn you though, I tried it a couple months back, and it was not production grade yet, it did crash from time to time.

Anyway, if you still want to continue heading your way I'll try answering your question: I think you are messing too much with the way these stuff should work. try understanding first how handlers work with threads.

Do anything you want on your thread:

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

When your data is ready, tell the handler to put it in a view and show it:

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...
            }
        }
    };

This goes to everything that requires heavy processing/networking that shouldn't block your UI thread.

Hope this helps.




回答2:


Not sure what you are trying to achieve by refreshing a listView every few seconds. Anyways if you are writing some 2d games, you have to use SurfaceView , which is especially meant for continuous refreshing.




回答3:


Had the same problem and solved it using a pretty simple code.

Tips:

  • GridView must be refreshed by the UI thread
  • To display every change you must keep the loop and the Sleep method away from the UI thread


Solution:
  • Method to update the grid (put on your Activity that you build your GridView at the first place or wherever)

    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();
    

    }

  • Build the non UI Thread that does the work

public class DataReceiver implements 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();
        }
    }

}

}



来源:https://stackoverflow.com/questions/8947881/android-updating-gridview-multiple-times-after-x-seconds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!