1

x 秒ごとに Android のビューを更新する際に問題が発生しています。

アンドロイドがどのように機能するかを知るために、私は小さなゲームを書いています。ゲームループを保持する GameController があります。ループ内でロジックが実行され、その後 GUI に変更が通知されます。

問題は、変更がビューに表示されないことです。ビューは、ゲーム ループが終了するまで同じままで、その後 1 回だけ更新されます。

これが私のコードです(重要な部分):

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

ゲームアクティビティ.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の異なるスレッドで実行され、同じスレッドで実行されると、ロジックがビューをブロックすることはできません。どんな助けでも大歓迎です。

// 編集:

new Thread(c).start(); を試してみると LogCat sais: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

Looper.prepare(); を追加すると、: java.lang.RuntimeException: アクティビティ ComponentInfo{GameActivity} を開始できません: java.lang.RuntimeException: スレッドごとに作成できるルーパーは 1 つだけです

this.runOnUiThread(c); を試してみると エラーはありません。

4

3 に答える 3

2

まず、これはゲームをクレートする方法とは思えませSurfaceViewGLSurfaceView。Android 用の Cocos2d を探すこともできます。これは (iPhone から移植された) 2D プラットフォームであり、生活を楽にします : 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 スレッドをブロックしてはならない重い処理/ネットワークを必要とするすべてのものに当てはまります。

お役に立てれば。

于 2012-01-20T21:39:14.083 に答える
0

listView数秒ごとに更新することで何を達成しようとしているのかわかりません。とにかく、いくつかの 2D ゲームを作成している場合は、 を使用する必要がありますSurfaceView。これは、特に継続的な更新を目的としています。

于 2012-01-20T21:31:31.487 に答える