次の形式のレコードで満たされたデータベースがあります。私のアプリケーションに実行させたいのは、外部データベースからレコードを選択し、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インタラクションを設計するためのより良いアプローチはありますか?追加のビューが必要ですか?