0

次の形式のレコードで満たされたデータベースがあります。私のアプリケーションに実行させたいのは、外部データベースからレコードを選択し、SurfaceViewを使用してそれらのレコードを電話の画面に表示することです。

現在、アプリケーションの記録収集部分を担当するアクティビティとサービスがあります。アクティビティはインテントをサービスに渡し、サービスは表示する必要のあるレコードを返すことで応答します。レコードはDataクラスのインスタンスとしてプログラムに保存され、ビュー内の要素を描画する場所の画面座標を持っているだけです(DB内のすべてのレコードに円を描画しているだけです)。

簡潔にするために、サービスは含めませんが、Activityクラスのスケルトンと表示したいデータを含めます。

public class Data{
    private int x;
    private int y;
    private int id;
    private int shape;

    /*
    * Getters and setters for class properties
    */
}

public class Displayer extends Activity {
    int ht;
    int wt;
    dataReceiver dreceiver; 
    public static Map<String, Data> Info; 
    private LinearLayout linear; 
    private static final int RADIUS = 20;
    Panel panel;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        panel=new Panel(this);
        setContentView(panel);

        Intent scv = new Intent(this, DataService.class);
        startService(scv);
    }
    /*
    * Various other methods to take care of onDestroy, onPause, etc.
    */

    public class dataReceiver extends BroadcastReceiver {
        //Get new data from intents sent by the Service and store it in Info variable

        //Update the Testing Map data-structure in the Panel SurfaceView with new records
        panel.setData(Info);

    }
}

私が抱えている問題はSurfaceViewに関係しています。多くの人が私が通常のビューだけを使用することを提案することを理解していますが、私のアプリケーションには多くの要素が含まれているため、SurfaceViewは私のニーズにはるかに適しています。以下は、スレッドを管理するためのネストされたクラスを含む、SurfaceViewクラスのスケルトンです。

public class Panel extends SurfaceView implements SurfaceHolder.Callback {
    private PanelThread _thread;

    private Paint circlepaint;
    private Paint textpaint;

    private static int CircleColor = Color.YELLOW;
    private static int TextColor = Color.RED;
    private static Map<String, Data> Testing;

    public Panel(Context context, Map<String, Data> entries) {
        super(context);

        getHolder().addCallback(this);
        _thread = new PanelThread(getHolder(), this);
        setFocusable(true);

        textpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textpaint.setStyle(Style.FILL_AND_STROKE);
        textpaint.setColor(TextColor);

        Testing = new HashMap<String, Data>();
        // Log.d("TestingSize",String.valueOf(Testing.size()));
        if (!(Testing.isEmpty())) {
            Testing.clear();
        }

        for (Map.Entry<String, Data> e : entries.entrySet()) {
            String keyvalue = e.getKey();
            Data v = e.getValue();
            Panel.Testing.put(keyvalue, v);
        }

    }

    public Panel(Context context) {
        super(context);
        getHolder().addCallback(this);
        _thread = new PanelThread(getHolder(), this);
        setFocusable(true);
        textpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textpaint.setStyle(Style.FILL_AND_STROKE);
        textpaint.setColor(TextColor);
        Testing = new HashMap<String, Victims>();

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // TODO Auto-generated method stub
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        _thread.setRunning(true);
        _thread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        /* we have to tell thread to shut down 
        * & wait for it to finish, 
        * or else it might touch the Surface 
        * after we return and explode
        */

        boolean retry = true;
        _thread.setRunning(false);
        while (retry) {
            try {
                _thread.join();
                retry = false;
            } catch (InterruptedException e) {
                // we will try it again and again...
            }
        }
    }   
    /*If new records are received 
    * from the service, they can be updated 
    * using this method
    */
    public void setData(Map<String,Data>Info){
        Testing=Info;
    }

    /*
    * Iterate over all contents of Testing List and display them to the screen
    */
    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (!(Testing.isEmpty())) {
            for (Map.Entry<String, Victims> e : Testing.entrySet()) {
                Data d = e.getValue();      
                canvas.drawCircle(d.getX(), d.getY(), 10, circlepaint);
            }
        }

        canvas.save();
        canvas.restore();
    }

    /*
    * Nested class to manage the threads for the SurfaceView
    */
    class PanelThread extends Thread {
        private SurfaceHolder _surfaceHolder;
        private Panel _panel;
        private boolean _run = false;

        public PanelThread(SurfaceHolder surfaceHolder, Panel panel) {
            _surfaceHolder = surfaceHolder;
            _panel = panel;
        }

        public void setRunning(boolean run) {
            _run = run;
        }

        public SurfaceHolder getSurfaceHolder() {
            return _surfaceHolder;
        }

        @Override
        public void run() {
            Canvas c;
            while (_run) {
                c = null;
                try {
                    c = _surfaceHolder.lockCanvas(null);
                    synchronized (_surfaceHolder) {
                        _panel.onDraw(c);
                    }
                } finally {
                    // do this in a finally so that if an exception is thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        _surfaceHolder.unlockCanvasAndPost(c);
                    }
                }
            }
        }
    }//end of PanelThread

}//end of Panel

私が抱えている問題は、Panelクラスを最初に呼び出すと、サービスから新しいレコードを取得することになり、その結果、InfoMapのデータ構造が更新されることです。ただし、私のPanelクラスはループに陥り、新しいDataオブジェクトを受け取ることはありません。私が見つけたSurfaceViewのすべての例には、SurfaceViewクラス自体のメソッドの更新が含まれています(たとえば、画面に触れて新しい画像を作成するなど)。悲しいことに、私はこの特定の問題に困惑しています。Activity / SurfaceViewインタラクションを設計するためのより良いアプローチはありますか?追加のビューが必要ですか?

4

1 に答える 1

1

コードをざっと見てみると、問題は、PanelThread で操作中に UI スレッドからデータ構造を更新しようとしていることにあると思います。また、Activity クラスと Panel も同期していないようです。Panel クラスに setData メソッドはありませんが、Testing 静的メンバー変数が更新されると思います。

私の提案:

1 - テストは静的であってはなりません。基本的に、クラスのこのインスタンスに関連付けられています。2 - データに触れるときは同期を使用します (テスト)。これは、データの設定と読み取りの両方で行う必要があります。3 - スリープまたは待機呼び出しを実行ループに入れます。これにより、アクティビティ UI スレッドがテストを更新する時間が与えられます。また、バッテリーを節約し、更新のフレーム レートを選択できます。

于 2010-08-06T10:12:22.527 に答える