Reputation: 7937
I have written a game (I'll give it the name "Gamer") in which I have the following general structure (the code has been much simplified):
public class Gamer extends Activity implements View.OnClickListener
{
public void onCreate(Bundle savedInstanceState)
{
mpt = new MicksPanelThing(this);
}
}
public class MicksPanelThing extends SurfaceView implements SurfaceHolder.Callback
{
public MicksPanelThing(Context context)
{
super(context);
micks_thread_thing = new MicksThreadThing(getHolder(), this);
getHolder().addCallback(this);
setFocusable(true);
}
void updateView()
{
final SurfaceHolder holder = getHolder();
try
{
Canvas canvas = holder.lockCanvas();
if(canvas != null)
{
onDraw(canvas);
holder.unlockCanvasAndPost(canvas);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void onDraw(Canvas canvas)
{
// blah
}
}
class MicksThreadThing extends Thread
{
public MicksThreadThing(SurfaceHolder surfaceHolder, MicksPanelThing mpt)
{
// blah
}
public void run()
{
while (this_thread_is_currently_active)
{
micks_panel_thing.updateView();
}
}
}
The game was all working fine and was very robust. Now I wanted to test for a certain condition and, if it was true, put up an AlertDialog. I presumed that I could put this code within my onDraw method. I then got a message "Can't create handler inside thread that has not called Looper.prepare()" - this is confusing me because I assumed that the onDraw method was being executed by the main thread for which I presumed I needn't set anything up.
I presume I could solve this by either moving my test and dialog to somewhere within the main thread (where?) or by adding some Looper.prepare() code somewhere.
Please can someone tell me which would be easier - and where should any necessary code go.
Upvotes: 2
Views: 964
Reputation: 24181
try to use the method : runOnUIThread()
to force the app to run your code on the mainThread ( which is the UIThread
) , Example :
class MicksThreadThing extends Thread
{
public MicksThreadThing(SurfaceHolder surfaceHolder, MicksPanelThing mpt)
{
// blah
}
public void run()
{
Gamer.this.runOnUiThread(new Runnable(){
@Override
public void run(){
//update/create your views here
while (this_thread_is_currently_active)
{
micks_panel_thing.updateView();
}
}
});
}
}
Other solution is : instead of using a Thread
,you can use an AsyncTask
Upvotes: 2
Reputation: 11776
the main thread is the ui thread... so you can use Handler
or the onPostExecute() or onPreexecute()
in the AsyncTask
.
Upvotes: 0
Reputation: 68177
do it in this way:
class MicksThreadThing extends Thread
{
public MicksThreadThing(SurfaceHolder surfaceHolder, MicksPanelThing mpt)
{
// blah
}
public void run()
{
while (this_thread_is_currently_active)
{
//micks_panel_thing.updateView();
Gamer.this.runOnUiThread(new Runnable(){
@Override
public void run(){
micks_panel_thing.updateView();
}
});
}
}
}
Upvotes: 1
Reputation: 5407
You can't update the UI from a normal Thread.
Use runOnUiThread()
for updating UI.
Upvotes: 0
Reputation: 43098
You call onDraw(canvas);
from MicksThreadThing. Obviously, it is not the main thread of the application. The main thread is those, which onCreate()
of your activity is called.
Upvotes: 0