i been working on a game with no bitmaps or anything, I'm using rectangles as objects and changing their color for their purpose like a red rectangles for player and gray rectangles for walls. My question is what is the right way to replace the rectangles with bitmaps/images?
I know to load Bitmaps you can just do this :
Bitmap randomBitmap = BitmapFactory.decodeResource(getResources(),
com.example.android4gametest.R.drawable.ic_launcher);
Should i load all my Bitmaps and pass them to their Classes or should i load the bitmap inside their class instead of passing it ? and how would i do that because i cannot use the BitmapFactory because i have no access to the getResources()! or should i load my bitmaps/images from my assets folder which i know i wont have the same "tools" you can say to mess with the bitmap.
MainActivity
public class MainActivity extends Activity {
Game theGame;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new Game(this));
}
}
The Game Panel
public class Game extends SurfaceView implements SurfaceHolder.Callback {
GameThread _thread;
public Game(Context context) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
_thread = new GameThread(getHolder(), this);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
_thread.setRunning(true);
_thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
#Override
protected void onDraw(Canvas canvas) {
Log.d("OnDraw", "it is Drawing");
canvas.drawColor(Color.BLUE);
}
public void update() {
// TODO Auto-generated method stub
}
}
GameLoop Nothing here
public class GameThread extends Thread{
/*FPS Code*/
private final static int MAX_FPS = 30;
private static final int FRAME_PERIOD = 1000/MAX_FPS;
protected SurfaceHolder holder;
protected Game game;
private boolean isRunning = false;
public GameThread(SurfaceHolder _holder, Game _game) {
this.holder = _holder;
this.game = _game;
}
/**
* Returns True if the game is still running and False if the game is over
* #return
*/
public boolean isRunning() {
return isRunning;
}
/**
* Set to true for the game loop to start
* #param isRunning
*/
public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}
#Override
public void run() {
Canvas c;
Log.d("Pallyways", "Starting game Loop");
long beingTime;
long timeDiff;
int sleepTime;
int framesSkipped;
sleepTime = 0;
while(isRunning){
c = null;
try{
c = holder.lockCanvas();
synchronized(holder){
beingTime = System.currentTimeMillis();
framesSkipped = 0;
game.update();//Update
game.onDraw(c);//Redraw
timeDiff = System.currentTimeMillis() - beingTime ;
sleepTime = (int) (FRAME_PERIOD - timeDiff);
if(sleepTime>0){
try{
Thread.sleep(sleepTime);}
catch (InterruptedException e) {
e.printStackTrace();}
finally{}
}
while(sleepTime<0 && framesSkipped < 5){
game.update();
sleepTime+= FRAME_PERIOD;
framesSkipped++;
}
}
}finally{if(c!=null){
holder.unlockCanvasAndPost(c);
}
}
}
}
}
Hero Class I have not started but i would like to know how to load a bitmap on a class that is on a different Package
package com.example.android4gametest.Actors;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import com.example.android4gametest.R;
public class Hero {
//getContext() gives me an error and that is because it does not have a reference
private Bitmap hero = BitmapFactory.decodeResource(getContext().getResources(),
R.drawable.ic_launcher);
public Hero(){
}}
Depending on the sizes/number of bitmaps, it may be fine to load them in the constructor of your Game class. Be aware though, if you're loading too many/too big bitmaps into memory at once, you may run into some OOM errors or a lag in when your first draw call gets made. You have to be sure you're nulling, recycling your bitmaps efficiently when you no longer need them. Struggled with this issue with my first game
Do not load the Bitmap in your game object's constructors. If any of those Bitmaps would be used by multiple objects (i.e. an enemy class), then if you loaded them in your object's constructors you would have multiple copies of the Bitmap in memory. This could lead to an OutOfMemoryException. Instead load your Bitmap outside of your constructors (in your game thread or game panel) and then pass the Bitmap objects to the constructors or setters and set your private Bitmaps that way. You'll only have to keep a limited number of Bitmaps in memory.
You may also want to consider a loading "screen" which displays a progress bar or spinner while you load those Bitmaps.
Where you load is not important. I think your main issue is accessing the resources. In a view, you can call:
getContext().getResources()
Edit:
So in the method signature of the constructor of Hero add Context as a parameter:
public Hero(Context context){
private Bitmap hero = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
}
DO NOT! use dynamic objects.. I mean Do not create dynamic objects in a game at all, these will trigger the GC and make everything stutter when it's running whenever it wants. You must take control over everything yourself and use static/final "objects" and arrays on the obstacles and enemies. The objects will be loaded on to the heap at startup, which means that you will have them loaded until the app is shut down. Therefore you must find the balance between what to have in these static objects and not, but it's easy when you have found it.
The bitmaps should be loaded outside these static non-dynamic objects, the objects should only do the calculations.
And never use any unnessesary calculations, loops or Thread.sleep in between your
c = holder.lockCanvas(); and holder.unlockCanvasAndPost(c); like you're doing in your code.
This can and will finally make the game flicker.
Regards,
Me
Related
I've got myself a mediocre game going for myself. It has a main menu activity that when you click play starts a new game play activity. When you lose the game you can either retry or go back to the main menu. the back button on the gameplay activity is just a ractangle with this coding.
if (GlobalVariables.GAMEOVER && backButton.contains((int)(event.getX()), (int)(event.getY())))
{
Intent backButtonIntent = new Intent(context, MainMenuActivity.class);
context.startActivity(backButtonIntent);
}
The program does not crash and it does switch to the mainmenu activity but it is frozen and no buttons are clickable. and here is the error i get.
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawColor(int, android.graphics.PorterDuff$Mode)' on a null object reference
at android.view.SurfaceView.dispatchDraw(SurfaceView.java:451)
at android.view.View.draw(View.java:17472)
at android.view.SurfaceView.draw(SurfaceView.java:442)
at com.example.jordanschanzenbach.myapplication.GamePanel.draw(GamePanel.java:84)
at com.example.jordanschanzenbach.myapplication.MainThread.run(MainThread.java:52)
here is the code that it is pointing to in the game panel. "super.draw(canvas)"
public void draw(Canvas canvas)
{
super.draw(canvas);
backGround.draw(canvas);
gameFloor.draw(canvas);
gamePlayScene.draw(canvas);
}
i understand that this is a nullpointerexception and a duplicate question. but i dont understand why when i switch to my main menu activity it is causing this error when the game panel isn't even linked to the main menu activity. Please help a young student :) thank you and if you would like to see any other code i will edit this post immediately.
Check if the thread responsible for calling the draw method was left running before starting another activity. I'm not quite sure but it probably still tries to render on the SurfaceView even if it has already been detached from the window.
Edit:
I was able to replicate your problem. The thread that handles the drawing does not always instantly get the updated value of the variable you use as a while loop condition. You can choose to perform synchronization and/or other threading stuff, but you can simply try to break the while loop like how I did in the code below. Also, try to stop your drawing thread by making your while loop condition false inside the SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder).
public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {
private TextPaint paint;
private volatile boolean isDrawing;
private DrawingThread drawingThread;
public GamePanel(Context context) {
super(context);
initialize();
}
// omitted the other constructors for brevity
private void initialize() {
...
drawingThread = new DrawingThread();
// do this so that you can get an surface updates
getHolder().addCallback(this);
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawText("Hello, world", 20, 20, paint);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
isDrawing = true;
drawingThread.start();
// start drawing only after the surface was created
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
isDrawing = false;
// try to stop the drawing thread when the surface
// is destroyed
}
private class DrawingThread extends Thread {
#Override
public void run() {
while (isDrawing) {
try {
Canvas canvas = getHolder().lockCanvas();
// check if canvas is null just to make sure
if (canvas == null) break;
draw(canvas);
getHolder().unlockCanvasAndPost(canvas);
} catch (IllegalArgumentException e) {
// This is thrown by SurfaceHolder#lockCanvas().
// Break when the surface has already been destroyed
// but the variable `isDrawing` is still true.
break;
}
}
}
}
}
i'm making a game in libgdx but i'm new and i donĀ“t know if my code is the correct form or the best way to do it.
i'm trying to make the basis of the game:
a screen manager to implement a Menu,
an option screen
a loading screen
a game screen
a pause Screem
a game over screen
In the loading screen I like to do something like Dragon Ball when the loading screen allow us to make goku eat rice, the pause screen needs to draw some statistics and options something like Megaman or Castlevania, the menu do something when the player touch a button something like move the camera or open a door, or move to another "scenario" showing another options, and the game over screen needs to previously gives the player the opportunity to win some life to not lose the game.
I try to make this in this form:
I have the main class of the game with the constructor, and the overriden metods create(), render(), resize() and dispose(), the variables for a camera, a viewport, a Spritebatch, a int to store the current screen, and a manager for the screens.
public class BOS_Project extends Game {
OrthographicCamera camera;
Viewport viewport;
SpriteBatch batch;
AssetManager manager = new AssetManager();
int actualScreen = 0;
public BOS_Project(){
camera = new OrthographicCamera();
camera.setToOrtho(false, screenWidth, screenHeight);
viewport = new FitViewport(screenWidth, screenHeight);
}
#Override
public void create(){
batch = new SpriteBatch();
}
#Override
public void render(){
actualScreen = 1;
ScreenManager.getInstance().showScreen(1, this);
super.render();
}
#Override
public void resize(int width, int height){
viewport.update(width, height);
}
#Override
public void dispose(){
batch.dispose();
}
}
Also the class ScreenManager is singleton, and
public class ScreenManager{
private static ScreenManager instance;
private Game game;
Screen screen;
private ScreenManager(){
super();
}
public static ScreenManager getInstance(){
if(instance == null){
instance = new ScreenManager();
}
return instance;
}
public void initialize(Game game){
this.game = game;
}
public void showScreen(int currentscreen, BOS_Project game){
if(currentscreen == 1){
if(screen!=null)
screen.dispose();
screen = new LoadingScreen(game, game.actualScreen);
game.setScreen(screen);
}else if(currentscreen == 2){
if(screen!=null)
screen.dispose();
screen = new GameScreen(game);
game.setScreen(screen);
}else{
if(screen!=null)
screen.dispose();
screen = new MenuScreen(game);
game.setScreen(screen);
}
}
The other classes are the MenuScreen, GameScreen and Loading Screen.
Loading Screen:
public LoadingScreen(BOS_Project game2, int screen2){
game = game2;
screen = screen2;
game.manager.load("button.png", Texture.class);
game.manager.finishLoadingAsset("button.png");
sprite1 = new Sprite(game.manager.get("button.png", Texture.class));
sprite1.setPosition(0, 0);
//This is a method to load the assets for the especific screen
game.load(screen);
}
#Override
public void render(float delta){
if(game.manager.getProgress()==1) {
if (time < 3) {
Gdx.app.log("Loading: ", "90.0");
}
}else {
Gdx.app.log("Loading: ", String.valueOf(game.manager.getProgress() * 100));
}
game.manager.update();
batch = game.batch;
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
sprite1.draw(batch);
if(game.manager.getProgress()==1 && time > 3){
if(screen==1) {
ScreenManager.getInstance().showScreen(2, game);
}else{
ScreenManager.getInstance().showScreen(3, game);
}
}else{
time += delta;
}
batch.end();
super.render(delta);
}
The Menu and Game classes are similar to loading, only call the assets and draw some sprite on the render method.
This code function well to change screens but I don't know if is the correct form, and another big question is how to manage the pause screen, because I manage this only storing a variable if the variable is pause the render method draw something, if not draw the normal game, but if I want to change the options and images of the pause I need to check variables to know what the pause needs to draw.
if(pause){
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
spritePause.draw(batch);
batch.end();
}else if(game){
batch.begin();
spriteGame.draw(batch);
batch.end();
}
So, am i doing it right? or what would you recommend me? Some examples or maybe specific tutorials to achieve this would be great.
There is not only one correct way of managing screens. Libido gives you the freedom to do it exactly how you please. You can extend the Screen class to make screens for the different needs of your project. You can manage your screens as states and manage them with a state manager.
Regarding the Pause and Game Over screen, you can do that in different ways too.
You can have a dedicated screen to switch to or you can have a Pause and GameOver state in your Game state/screen and show the Pause/GameOver elements on top of your gamescreen while the game is still in the background.
So there is not a single correct way of doing it. The correct way is what works for your game.
For some inspiration:
pixnbgames.com : How to manage screens
Brent Aureli : Game State Manager
As #IronMonkey has answered, there is no "correct" way.
I do it with one GameScreen class only, and have a lot of different states inside the GameScreen class. The GameScreen class is very simple and short (100-200 LOC), and is responsible for switching between states. States are similar to the GameScreen class, but they can be entered and exited without the need to instantiate new objecs.
class GameScreen extends ScreenAdapter implements Disposable {
GameState menuState;
GameState playState;
GameState currentState;
public GameScreen(final MyGame game) {
menuState = new MenuState(this);
playState = new PlayState(this);
}
public void setState(GameState state) {
if(currentState == state) return;
// states have a method 'exit' where you can pause them or finalize something
if(currentState != null)
currentState.exit();
currentState = state;
// also states have 'enter' where you can unpause or init something when entering
currentState.enter();
}
public void render(float delta) {
currentState.render(delta);
}
}
First, this is very resource efficient, because the needed states are created only once when the game is started. Second, because you never destroy the states, but just change them and call enter/exit, they always retain perfectly their current state, i.e. variables, objects and everything and when you go back to a state, it is exactly as it was before you left it.
GameState is interface and you are free to implement it as you wish.
public interface GameState
{
public void enter();
public void exit();
public void update(float delta);
public void render(SpriteBatch batch, float delta);
public String toString();
public void dispose();
}
I believe the problem I have is that gameThread won't work unless I have use GL10 gl in gameview.drawFrame(). I've tried creating a Object gl passing that in but still wont work. Also is it wrong to use game.onResume to update the game?
I've created an instance of the gameThread inside of Main.class and classed the
public class GameThread extends Thread {
Object gl;
private static int MAX_FRAME_SKIPS;
private static int FRAME_PERIOD;
private OpenGLActivity game;
private MyGLRenderer gameView;
private boolean gameRunning = true;
private boolean running = false;
Handler handler = new Handler();
public GameThread( int maxFPS, int maxFrameSkips) {
game = new OpenGLActivity();
gameView = new MyGLRenderer();
MAX_FRAME_SKIPS = maxFrameSkips;
FRAME_PERIOD = 1000 / maxFPS;
gl = new Object();
}
#Override
public void run() {
long beginTime;
long timeDiff;
int sleepTime;
int framesSkipped;
beginTime = System.currentTimeMillis();
framesSkipped = 0;
this.gameRunning = this.game.isRunning();
this.game.onResume(); // Update game
this.gameView.onDrawFrame((GL10) gl); // Render the game
timeDiff = System.currentTimeMillis() - beginTime; // Calculate cycle length
sleepTime = (int) (FRAME_PERIOD - timeDiff); // Calculate time available to sleep
// Checks if got time to sleep, either sleeps thread or catches up
if (sleepTime > 0) {
if (this.gameRunning && running) {
handler.postDelayed(this, sleepTime);
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
this.game.onResume(); // Update without rendering
sleepTime += FRAME_PERIOD; // Add frame period to check if in next frame
framesSkipped++;
if (this.gameRunning && running) {
this.run(); // No time to wait! RUN! CATCH UP!
}
}
}
}
public void setRunning(boolean running) {
this.running = running;
}
}
public class Main extends Activity{
GameThread gt = new GameThread(48, 100);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
}
public void PlayGame(View v) {
Intent intent = new Intent(Main.this, OpenGLActivity.class);
startActivity(intent);
gt.setRunning(true);
}
The fact that you don't have a GL10 object is only a symptom here. In fact, I don't think that's ever used on Android. It's part of the javax.microedition.khronos.opengles package, which I figure is some kind of standard Java OpenGL ES interface. I'm not sure if it's functional, but I certainly have never seen anybody use it.
The OpenGL interfaces that are normally used in Android are in the android.opengl package, and are named GLES10, GLES11, GLES20, GLES30, GLES31.
On those classes, all the methods are static. So you never really need an object instance to make OpenGL calls.
But, and this is your actual problem: To make OpenGL calls, you need to create an OpenGL context, and make it current. You will also need a rendering surface. There are two main options for this:
The (moderately) hard way by using the EGL14 interface (or EGL10 if you need to support API levels lower than 17).
You can go the more convenient and widely used route, and use a GLSurfaceView, which creates the context and rendering surface for you.
I recommend that you start with the official tutorial in the Android documentation. All of the above will become much clearer once you go through this: http://developer.android.com/training/graphics/opengl/index.html.
You should also be aware that OpenGL ES 1.x is mostly considered obsolete. ES 2.0 and higher versions are much more widely used these days.
I am writing a small Android game using a SurfaceView class. The outline of the clas is as follows
class GameView extends SurfaceView implements Runnable {
Thread drawThread;
boolean drawThreadIsRunning;
Context context;
SurfaceHolder surfaceHolder;
Canvas canvas;
public GameView(Context context)
{
super(context)
this.context = context;
surfaceHolder = getHolder();
//...
}
public void resume() {
// starts drawing Thread
}
public void pause() {
// stops drawing Thread
}
public void run() {
while (drawThreadIsRunning) {
if (!surfaceHolder.getSurface().isValid())
continue;
canvas = surfaceHolder.lockCanvas();
update(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
private void update(canvas)
{
updateCoordinates(canvas);
updateDrawings(canvas);
e.t.c.
}
}
What I want to know is whether or not it's a good idea to use the update() method the way I have. Between the locking and the unlocking of the canvas, the update method moves the game elements, draws them, updates the score and so on. Will this have a negative impact on the performance? Is there a better way of structuring this?
It looks fine to me. The only thing that you could do would be to move the calls to updateCoordinates(); updateDrawings(); etc. into the run() to save the overhead of that additional method call but it shouldn't make a noticeable difference.
I have a database filled with records in the following format: . What I want my application to do is select records from an external database, and display those records on the phone screen using a SurfaceView.
Currently, I have an Activity, and a Service responsible for the record-gathering portion of the application. The Activity passes an intent to the Service, and the Service responds by returning the records that need to be displayed. The records are stored in my program as instances of the Data class, and merely have the screen-coordinates of where the element should be drawn in the View (I am just drawing a circle for every record in the DB).
For the sake of brevity, I won't include the service but I will include a skeleton of the Activity class and the Data that I wish to display.
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);
}
}
The problem that I am having pertains to the SurfaceView. I realize that many people are going to suggest that I use just a regular View, but my application involves a lot of elements, so a SurfaceView would be much more suitable for my needs. Below is a skeleton of my SurfaceView class that contains a nested class to manage the threads.
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
The problem that I'm having is that once I make the initial call to the Panel class, I'm going to be getting new records from the service, and consequently, my Info Map data-structure is going to get updated. However, my Panel class just gets stuck in a loop and never receives any new Data objects. All examples of SurfaceViews I've found have involved updating them methods within the SurfaceView class itself (e.g. touching the screen and creating a new image, etc.) Sadly, I'm stumped on this particular problem. Is there a better approach for designing my Activity/SurfaceView interaction? Is an additional View required?
From a quick look at your code I think the problem is that you are trying to update a data structure from the UI thread while acting on it in the PanelThread. It also looks like your Activity class and Panel are also out of sync - I don't see the setData method in your Panel class, but I assume it updates the Testing static member variable.
My suggestions:
1 - Testing should not be static - it's fundamentally associated with this instance of the class.
2 - Use Synchronize when touching the data (Testing). This should be done for both setting and reading the data.
3 - Put a sleep or a wait call in your run loop - this gives time for the activity UI thread to update Testing. Also saves battery and allows you to pick a frame rate for updates.