A lot of android games are not even large enough in scope to justify save/load or options/preferences, never mind custom characters and the like simply because they are played offhand for 10 minutes on the train home.
Don't make the mistake I did of embarking on something with a large scope for a first android game. Make a bunch of smaller games then go for something larger
Android specifics wise:
I would recommend having almost all the game in one activity class. Android works on the idea that each activity is like a mini-app, semi-independent of the other activities in the app. The app is essentially a stack of activities, with the user seeing which ever is on the top.
When you pop one off the top, it generally gets destroyed and will be recreated next time the user starts a new activity (startActivity intent). This makes it hard to maintain states between activities and leads to a single activity architecture
You may want to have a Home screen type activity with a "New Game/Load Game/Options" menu on it, and make that the launch activity. However, you will end up having to have an in-game menu as well in your game activity, which will have most of the same functions in it
My own app, I made a "MenuActivity" that has the functions that launch a new game, save, load, change options. Then my HomeActivity extends that, as does my GameActivity.
Since everything is in one Activity class, I would recommend making a heirarchy of activity classes and using private, protected and default scope lots. Doing it this way, you at least can split things up into different file to stop from having one unmanageable Activity file. E.g. for my own app:
GraphicsEngine extends MenuActivity.
PhysicsEngine extends GraphicsEngine.
GameLogicActivity extends PhysicsEngine.
UIActivity extends GameLogicActivity.
Since my app is 3D opengl-es, a lot of stuff I do doesn't work cross-activities so everything is in the same activity, so maybe I'm biased towards using one activity architecture
For the game activity, You have two threads (or 3 if you are doing 3D opengl stuff). One thread is the UI/main thread. This is the thread the activity gets started and runs in and is given to you by android.
This UI thread is the only one you can update UI elements (views, layouts etc) in. It is also the one where any listeners for user input will run. You don't see any of the mechanics of the UI thread, just that it runs in a loop in the background somewhere.
The second thread, you make yourself (I would recommend using AsyncTask, despite all its shortcomings). This does all the non-UI things you do in a normal game loop, such as updating movement, calculating collisions, combat calculations and so on.
You make this AsyncTask thread/class as an inner class of your activity. That way, you can have some activity-wide-scope objects (
Vector<Spaceship>) that can be accessed by both UI thread and game loop thread.
Since the game logic is going on in the game loop thread, that is the only thread that will need to actually change the values of variables (update tank speed, reduce player HP). The UI thread just reads values, so there should be minimal concurrency issues.
The tricky bit is getting the UI thread to do updates on request of the game loop thread. There are a couple of ways to do this. If you read the AsyncTask documentation, it has publishProgress()/onProgressUpdate() method. This is actually adding stuff to the UI thread's queue of things to do next loop.
Handler does exactly the same thing, where you implement handleMessage() method and that method is actually executed by the UI thread next loop.
Finally, any user-input, being in the UI thread, you can update UI elements immediately from it (so inside the implementation of any onClick / onTouch listeners). If you need to update the game objects, you can either use things like synchronise, or you can implement your own queue of updates into AsyncTask that like the UI thread, it goes through next time it executes the game loop
Android Threading Guide.
As for the actual UI structure within the single activity, I recommend having a frame layout as your base layout. The child elements in a frame layout work like a queue. First element gets drawn first, second gets drawn on top of first, third on top of second.
This way, you can have multiple XML layout files and by managing the frame layout's children, can easily swap sets of views in and out.
If you always have the SurfaceView at the bottom (first child in the frame layout), then you can use all the usual android views/widgets (buttons, text views, scroll views) etc over the top of the surface view, which just does the graphics part of the game.
So for example, if something is loading, you can pause the game loop / just get it to skip everything, add an opaque 'loading' screen as the last child to the frame layout and the user will see 'loading' appear on their screen, quite unaware that other views are behind it. This way you don't have to remove views that take a long time to set up or cause complications each time they are added / removed.
I would also recommend using View.setVisibility lots. You could for example, add a whole 'inventory' layout to your base frame layout and then just setVisibility(View.Visible) on it when the user clicks to view their inventory, and setVisibility(View.Gone) when they close it again. That way, you aren't even managing the children of the frame layout so much as just adding everything and making things visible/invisible as and when the user does different things
This helps with threading again; as the user clicks to open their inventory, the onCLickListener is handled in the UI thread, the inventory is made visible therein, and the updateInventory method is called, again from the UI thread, with just getters on all the game objects being called
Here's the diagram I made for an earlier question about the single activity / frame layout idea: